コミュニティ/Netnews 斜め読み

トップ 差分 一覧 Farm ソース 検索 ヘルプ RSS ログイン

comp.lang.awk

  • Netnews の comp.lang.awk を適当に日本語訳して抜粋してあります。(本当に適当です)
  • 書き込んだ人の名前の部分はオリジナルの投稿者の名前に変更させていただきましたが、時間までは変更していません。詳しくは、comp.lang.awk を購読していただくか、Google グループの comp.lang.awk などで確認してください。
  • 件数が増えてきたら古いものから順に過去ログに移動します。過去ログは [complangawk] から参照できます。

最近のタイトル一覧

[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ]

comp.lang.awk

お名前
件名
本文

regexp matching ip address - Matthias Teege (2005年09月08日 23時21分12秒)

IP アドレスの 4 ブロックに相当する正規表現を探しています。

awk '{ if ( $2 ~ /[[:digit:]{1,3}]\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/) print $2; }'

でも、どの IP アドレスにも該当しませんでした。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/7a4567cecd18af8e/6a3606d18b68e341?hl=ja#6a3606d18b68e341


  • GNU awk を使っているようですが、--re-interval オプションを使うか、最近議論されたもの (オリジナルはこちら) を探してください。 - Jurgen Kahrs (2005年09月08日 23時23分05秒)
  • BSD なので、そんなことはないです。 - Matthias Teege (2005年09月08日 23時28分20秒)
  • 正しくは以下ではないでしょうか? - William James (2005年09月08日 23時31分22秒)
/[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}/

短くすると、

/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}/
  • gawk だとうまく動作します。 - Matthias Teege (2005年09月08日 23時33分43秒)
$  echo 111.111.111.111 | \
   awk '$0 ~ /([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}/'
$
$ echo 111.111.111.111 | \
   gawk --re-interval '$0 ~ /([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}/'
$ 111.111.111.111
  • つまり、あなたの awk は以下のどちらかだ。 - Ed Morton (2005年09月08日 23時35分39秒)
  1. あなたの awk は文字列クラス ([:digit:]) を受け付けないか
  2. あなたの awk は正規表現範囲指定 ({1,3}) を受け付けないか

どちらかです。なので、以下のものを試してください。

$ echo "111.111.111" | awk -v d="[0-9][0-9][0-9]" '$0 ~ d"."d"."d'
111.111.111

これは比較的新しい awk なら何でも動作するでしょう。

  • 以下のようなものを試してみました。 - Bob Harris (2005年09月08日 23時40分26秒)
echo 1 | awk '/1/'
1

echo 1 | awk '/1{1}/'
...nothing, nada, zilch...

echo 1 | awk '/1\{1\}/'
...nothing...

そこで、+ を使ってみませんか?

echo 111.111.111.111 |\
awk '/[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+/'

または

echo 111.111.111.111 |\
awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/'
  • でも、11181110023 でもマッチします。 - Patrick TJ McPhe? (2005年09月10日 01時21分54秒)
BEGIN { d = "([0-9]|[0-9][0-9]|[0-9][0-9][0-9])"
        p = "\\." }
$0 ~ "^" d p d p d p d "$"                                                                  

で、どうでしょう。

  • 以下を試してみてください。 - Don Stokes (2005年09月13日 22時07分16秒)
BEGIN {
        p = "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
        p = "^" p "\\." p "\\." p "\\." p "$"
}
$0 ~ p { ... }

{{comment}}


  • BSD は山ほどありますが、FreeBSD, OpenBSD, NetBSD などは皆 gawk なんですけどね。Jurgen Kahrs が正解かな。 - hi_saito (2005年09月08日 23時29分48秒)

Delete a character from a file - SailFan? (2005年09月08日 23時10分41秒)

ファイルから文字を取り除きたいです。その文字列は ? です。

gawk {gsub(/?/,\"\");print} infile > outfile

でうまくいきません。ファイルの文字は以下のようなものを想定しています。

ISA~01~830       ~00~          ~ZZ~AAAA   AAAAAA  ~12~9999999999~050828~1306~U~00401~000000201~0~P~@'?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/bff15cad9dfd453a/3b3a44d45a5f277f?hl=ja#3b3a44d45a5f277f


  • Windows を使っているのであれば、以下のようにしてみてください。 - William James (2005年09月08日 23時11分32秒)
gawk "{gsub(/?/,\"\");print}" infile > outfile
  • 動いているみたいですが、置換されていません。 - SailFan? (2005年09月08日 23時12分36秒)

やりたいことは "@'?" を "@'" に置換することです。

  • 8 進数表記を使うことができます。 - Patrick TJ McPhe? (2005年09月08日 23時16分26秒)
gsub(/\300/, "")

または範囲指定で、

gsub(/[\177-\377]/, "")

とできます。

  • これは awk の問題ではなく、Windows のシェルの問題なので、ファイルにして読み込ませてみてください。 - Ed Morton (2005年09月08日 23時18分14秒)
  • うまくいきました。 - SailFan? (2005年09月08日 23時18分44秒)

{{comment}}

find lines with a space in the second field - cumin (2005年09月08日 23時01分40秒)

第 2 フィールドのスペースを処理したいのです。

Q:\RxNorm\data>type spaces                                                                   
93005|Isordil Titradose
93006|Isordil
93007|Isordil Tembids
Q:\RxNorm\data>gawk "{if ($2 ~/ /) {print $0}}" spaces >nospaces                             
Q:\RxNorm\data>type nospaces                                                                 
Q:\RxNorm\data>      

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/a8d03a93113ea4cd/ca2d6fda1a41fe94?hl=ja#ca2d6fda1a41fe94


  • "|" がフィールドセパレータなので、うまくいってないのではないでしょうか? 以下のものを試してみてください。 - Ed Morton (2005年09月08日 23時03分06秒)
gawk -F\| '$2 ~ / /' spaces > nospaces
  • でも、うまくいきません。 - cumin (2005年09月08日 23時04分17秒)
#bn.awk                                                                                      
BEGIN{FS="\|"}
{$2~/ /}

というファイルを作ってみました。

C:> gawk -f bn.awk spaces > nospaces                                                         

何も表示されません。

  • ↑それは間違っています。 - William James (2005年09月08日 23時05分54秒)
BEGIN{FS="|"}
$2~/ /

です。{{comment}}

Multiple columns to add up - Nasir Mahmood (2005年09月07日 01時26分45秒)

3 つのファイルがあります。

----------------
File1
----------------
col1
col1
col1
col1
col1
----------------
File2
----------------
col2
col2
col2
col2
col2
----------------
File3
----------------
col3
col3
col3
col3
col3

これを以下のような 1 つのファイルにするアイデアはありますか?

col1  col2    col3
col1  col2    col3
col1  col2    col3
col1  col2    col3
col1  col2    col3

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/7586234d42cfe9cb/286a809ef398196c?hl=ja#286a809ef398196c


  • comp.unix.shell に投稿した回答をみてください。それとも awk での回答が必要ですか? - Ed Morton (2005年09月07日 01時27分53秒)
  • 1 行が長すぎなければ以下の方法で可能です。 - Ed Morton (2005年09月08日 22時50分23秒)
gawk '{f[FNR,ARGIND]=$0}END{for (i=1;i<=FNR;i++){ for(j=1;j<=ARGIND;j++) printf "%s ",f[i,j]; print ""}}' file1 file2 file3

このままでは最後にスペースが入るので、気になるなら除去しましょう。

  • ここで使っている f[FNR,ARGIND] は多次元配列ではなく awk の場合は SUBSEP を間に挟んだだけのインチキ多次元配列です。 - Ed Morton (2005年09月08日 22時53分49秒)
  • OFS を変更したものを用意しました。 - Loki Harfagr (2005年09月08日 22時55分03秒)
$ awk '{v[ARGIND,FNR]=$0}
END{for(j=1;j<=FNR;j++)
  {for(i=2;i<=ARGIND;i++)
    {printf v[i,j]((ARGIND>i)?OFS:X)} print ""}}' OFS=_ col1 col2 col3
$ echo ============ > 0
$ cat col1 0 col2 0 col3
A1
A2
A3
A4
A5
============
B1
B2
B3
B4
B5
============
C1
C2
C3
C4
C5
$ awk '{v[ARGIND,FNR]=$0} END{for(j=1;j<=FNR;j++){for(i=2;i<=ARGIND;i++){printf v[i,j]((ARGIND>i)?OFS:X)} print ""}}' OFS=_ col1 col2 col3
A1_B1_C1
A2_B2_C2
A3_B3_C3
A4_B4_C4
A5_B5_C5

{{comment}}

Problem with removing file1 lines from file2 - Jonny (2005年09月07日 00時13分28秒)

file2 から file1 の行を削除するのに以下のスクリプトを用いています。

"NR==FNR{f[$0]=1;next}!f[$0]++" file1 file2

file1 があるうちは良いのですが、file1 がなくなると file2 が全て削除されてしまいます。file1 がなくなっても、file2 が削除されない方法がありますか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/b8f55bc4f429768f/5bb4144036c4b29d?hl=ja#5bb4144036c4b29d


  • file1 のラインがなくなると awk がカウントできなくなり、そのまま次のファイルに移ります。 - Loki Harfagr (2005年09月07日 00時14分51秒)

二つのファイルに行を追加してやるか、file2, file1, file2 の順序でチェックしてみてください。(きっと Ed Morton が簡単な解を用意してくれるよ)

  • 自己解決しました。 - Jonny (2005年09月07日 00時19分47秒)
"BEGIN {while ((getline < \"file1\") > 0) ++t[$1]}{ if (!t[$1]) print }" file2
  • getline を使うことでうまくいくこともあります。 - Ed Morton (2005年09月07日 00時21分58秒)

ただし、getline は多くの作法があったり、注意したり、副作用もあります。この場合は必要ないでしょう。(以下参照)

  • NR == FNR ではうまくいきません。 - Ed Morton (2005年09月07日 00時24分28秒)

最初のファイルだけ処理するのであれば、以下の方法を用います。

"FILENAME==ARGV[1]{f[$0]=1;next}!f[$0]++" file1 file2

または gawk であれば、

"ARGIND==1{f[$0]=1;next}!f[$0]++" file1 file2
  • awk ではないですが、fgrep でできます。 - Eric Pement (2005年09月07日 01時22分44秒)
fgrep -v -f file1 file2

file2 を変更しない場合には、

fgrep -v -f /dev/null file2

です。

  • 以下のような方法があります。 - William James (2005年09月08日 22時49分05秒)
http://www.hirax.net/dekirukana5/miura/index.html
  • 初心者なんんですが、!f[$0]++ ってどういう意味ですか? - Sammy (2005年09月18日 18時42分40秒)
  • $0 のインデックスを持つ配列 f の要素が空列または 0 でなければ、配列 f をインクリメントするという意味です。 - Ed Morton (2005年09月18日 18時45分17秒)
  • うまくいきません。 - Sammy (2005年09月18日 18時47分23秒)
"NR==FNR{f[$0]=1;next}!f[$0]++" file1 file2

としているのですが、file1 がなくなると file2 がそのままになってしまいます。


  • なんか議論が振り出しに戻って、これに対して、Patrick TJ McPhee? がコメントしていますが、その後の Ed Morton のコメントが有用なので書いておきます。 - hi_saito (2005年09月18日 18時50分54秒)

getline を使うときには以下の変数がセットされます。

変数                   効果
getline                Sets $0, NF, FNR, and NR
getline var            Sets var, FNR, and NR
getline < file         Sets $0 and NF
getline var < file     Sets var
command | getline      Sets $0 and NF
command | getline var  Sets var

また、gawk では BEGIN で FILENAME もセットされます。したがって、アクションで再度 FILENAME と NR がセットされます。

つまり getline は挙動が異なるので、初心者には使って欲しくないわけです。これがはっきりしない限り、初心者に教えません。

$ cat file1
line 3
line 5
$ cat file2
line 1
line 2
line 3
line 4
line 5
line 6
$ cat v1.awk
BEGIN {
  while ((getline < ARGV[1]) > 0) f[$0]
  delete ARGV[1]
}
!($0 in f)
$ cat v2.awk
NR==FNR{f[$0];next}
!($0 in f)
$ awk -f v1.awk file1 file2
line 1
line 2
line 4
line 6
$ awk -f v2.awk file1 file2
line 1
line 2
line 4
line 6

この場合には v1.awk と v2.awk は同じ結果になります。

ただし、

$ awk -f v1.awk x=3 file1 file2
line 3
line 5
line 1
line 2
line 3
line 4
line 5
line 6
$ awk -f v2.awk x=3 file1 file2
line 1
line 2
line 4
line 6

となり、v1.awk は ARGV に依存します。もちろん、"-v x=3" であれば使えば問題ありません。

  • 簡単に以下のようにできます。 - John Savage (2005年09月25日 20時27分38秒)
gawk 'FILENAME==ARGV[1]{f[$0]=1;next} !f[$0]' file1 file2

これは mawk でも動作します。{{comment}}

how does gawk 1 filename work? - cumin (2005年09月03日 21時53分17秒)

UNIX の改行から、DOS の改行に変更するのに、

gawk 1 filename

とすることができます。

"1" は動作しますし、"1,4" とすることで範囲を指定することも可能です。

ただし、"1 || 23" は動作せず、"1 && 23" は動作します。

どうしてでしょうか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/b8f55bc4f429768f/5bb4144036c4b29d?hl=ja#5bb4144036c4b29d


  • gawk 1 filename は引用符なしで動作しますが、1 || 23 と 1 && 23 は引用符がないと gawk の前に shell が処理を行うため、正しく処理されません。 - ill Marcum (2005年09月03日 21時54分54秒)
  • gawk は以下のように動作します。 - Ulrich M. Schwarz (2005年09月03日 21時57分31秒)

"1" はパターンとして動作し、0 でない整数や最初が 0 でない範囲が指定されていれば、そのとおり動作します。ただし、

gawk '"a"' filenama

は "a" は 0 ではないため動作しますが、

gawk 'a' filename

は 0 となり、動作しません。それがリテラルと明示しないかぎり、そうした動作になります。

なお、1 || 23 と 1 && 23 はどちらも動作しました。

  • 1 の場合は正しいです。 - Ed Morton (2005年09月04日 01時09分31秒)

ただし、1 と 23 の時は、1 も 23 も TRUE になるはずです。

また、ダブルクォートがない場合、gawk の前に shell が解釈するでしょう。

$ printf "a\nb\nc\n" | awk 1
a
b
c
$ printf "a\nb\nc\n" | awk "1 && 23"
a
b
c
$ printf "a\nb\nc\n" | awk "1 || 23"
a
b
c
$ printf "a\nb\nc\n" | awk 1 && 23
a
b
c
bash: 23: command not found
$ printf "a\nb\nc\n" | awk 1 || 23
a
b
c

"awk 1 && 23" は "awk 1" が正常動作しているので "23" にパイプされて、23 というコマンドがなくて、えらーになっています。"awk 1 || 23" は "awk 1" が正常動作しているので、"23" に渡されず、エラーになりません。{{comment}}


  • いろいろおかしいのでツッコミを入れておきます。 - hi_saito (2005年09月03日 22時04分11秒)
    • 改行コードの変換に awk を使わないのが一番です。これは RS と ORS が明らかな場合、もしくはそのようにビルドされた環境でのみ動作します。
    • これは shell が明記されていないのですが、どうも Windows っぽいです。
    • 動作環境が明記されていないし、特に Windows で動作する gawk は独自に改良を加えている場合が多いので、注意した方が良いと思います。

regexp substitution in gsub( ) - karelnijs (2005年09月02日 00時04分37秒)

reg = "/^KEEPDATA(.*)$/"

if (gsub(reg, ";OLD &\n")) {
        print $0
        #...
    }

ここで、gsub() の中に "/^KEEPDATA(.*)$/" を書くと、その行が出力されますが、上のようにすると何も出力されません。この KEEPDATA という部分は変数として定義したいのですが、何が悪いのでしょうか?


  • 検索文字から "/" を削除します。 - Ed Morton (2005年09月02日 00時05分41秒)
reg = "^KEEPDATA(.*)$"

また、"(.*)$" は単に ".*" に置き換わります。".*" の部分を置換して、"KEEPDATA" を切り捨てるなら、gsub() の代わりに gensub() が必要になります。

  • 私も grep のようなものを作りますが、"/" は必要ありません。 - hi_saito (2005年09月02日 00時10分23秒)
  • / と " は正規表現と文字列を決定しています。 - Ed Morton (2005年09月02日 23時49分03秒)

gsub() や ~ の右辺に来たときには、ダイナミックに変化します。つまり、

$0 ~ "abc"
  "abc" = 文字列
$0 ~ /abc/
  /abc/ = 正規表現
pattern = "abc"
$0 ~ pattern
  pattern = ダイナミック正規表現

{{comment}}

"unexpected newline or end of string" in XP awk bat script - cumin (2005年08月31日 01時30分46秒)

dir | gawk "{sub(/n, ,$0}"

と Win XP 上で .bat ファイルとして実行したら、"unexpected newline or end of string" というエラーが出ました。

dir | gawk "{print $5}"

で各行に出る空行を削除したいのですが、提案がありますか?


  • そのままだと出力しませんよ。 - Chris F.A. Johnson (2005年08月31日 01時31分48秒)
dir | gawk "{printf \"%s \", $5}"

Windows で \" でエスケープできるんでしたっけ?

  • 以下のようにしてできました。 - cumin (2005年08月31日 01時34分09秒)
dir | gawk "{printf( $5\" \" )}"

print ではなく printf を使えばいいのですね。

  • 教えられた方法だとダメでした。 - cumin (2005年08月31日 01時36分25秒)
C:\scrap>dir   | gawk "{printf \"s \", $5}"                                                  
s s s s s s s s s s s s s s s s s s s s s s s

そこで、s の前後に % をはさみました。

C:\scrap>dir   | gawk "{printf \" \", $5}"                                                   
C:\scrap>cc                                                                                  
  • 私の言ったのと違うのでは? - Chris F.A. Johnson (2005年08月31日 01時40分07秒)

ちなみに、

"If you want to post a followup via groups.google.com, don't use
 the broken "Reply" link at the bottom of the article.  Click on
 "show options" at the top of the article, then click on the
 "Reply" at the bottom of the article headers." - Keith Thompson

つまり、

「group.google.com からポストするなら、壊れている "Reply" の
アーティクルのリンクボタンを押してはいけません。アーティクルの
トップで "show options" を押して、アーティクルヘッダーのボタンに
ある "Reply" をクリックしてください。」 - Keith Thompson
  • 以下のようになったんです。 - cumin (2005年08月31日 01時45分22秒)
dir   | gawk "{printf \"%s \", $5}"

という bat1.bat を作りました。

Q:\scripts\scrap>dir1.bat                                                                    

Q:\scripts\scrap>dir     | gawk "{printf \"s \", $5}"                                        
s s s s s s s s s s
Q:\scripts\scrap>                                                                            

しかしながら、フォーマット指定のない printf は動作しませんでした。そこで、

Q:\scripts\scrap>type dir1.bat                                                               
 dir | gawk "{printf( $5\" \" )}"

Q:\scripts\scrap>dir1.bat                                                                    

Q:\scripts\scrap>dir   | gawk "{printf( $5\" \" )}"                                          
is 820E-7BAF        free
Q:\scripts\scrap>                                                                            

としたんです。

  • バッチファイルでは % は特殊文字なので、リテラルとしての % を使うには %% としてください。 - Ted Davis (2005年08月31日 01時49分02秒)
  • 確かに Windows 上での shell (Explorer が shell だけど、この場合 cmd.exe) がやはりタコですね。ロングファイル名を使う必要がなければ、jgawk を使うことをお勧めします。 - hi_saito (2005年08月31日 01時51分03秒)

上記サイトには、jgawk 2.11.1+3.0 と jgawk 2.15.2+1.1 の両方がありますが、個人的には jgawk 2.11.1+3.0 が最も扱いやすいと思っています。ただし、jgawk 2.15.2+1.1 には時間関数が含まれており、時間関数を使う場合には後者が便利です。もっとも、時間関数の代用としては、date コマンドから取得したり、srand() から求めることもできます。

  • "%s" としたい場合には " を \" のようにします。 - Dave Thompson (2005年09月03日 21時44分52秒)
dir | gawk "{printf \"%%s \", $5}"

またはファイルにすることで、そのまま使えます。{{comment}}

Split a file into two (matches and non-matches) - Jonny (2005年08月28日 19時44分56秒)

正規表現にマッチしたものとマッチしていないものを別のファイルに出力することはできますか?


  • 以下のような方法があります。 - William James (2005年08月28日 19時45分58秒)
/Look for this/ { print >"out1" ; next }
{ print >"out2" }
  • つまり (ITYM)、以下のようなことですね。 - Kenny McCormack? (2005年08月28日 19時47分15秒)
{ print > ("out" (/Look for this/+1)) }
  • 以下のような方法があります。 - William Park (2005年08月28日 19時48分12秒)
grep -v 'regex' file > out1
grep    'regex' file > out2

同じ考えで、sed, awk, bash, python, perl でもできます。

  • grep での解法に対して、「awk でやるように」というツッコミが入っていますが、本題と関係ないので、無視させていただきます。 - hi_saito (2005年08月28日 19時52分52秒)

{{comment}}

Is there any text editor with AWK highlight? - Hans (2005年08月25日 21時37分13秒)

Kwrite (KDE の Editor) は良かったが、Windows で AWK ファイルの中身をハイライトさせるものはありませんか?


  • vim, emacs, jEdit がハイライト可能です。 - Benjamin Esham (2005年08月25日 21時38分31秒)
  • Crimson Editor も可能です。 - Doug McClure? (2005年08月25日 21時40分42秒)
  • UltraEdit も可能で、非常に使いやすいです。 - Jens Borchert Pedersen (2005年08月25日 21時43分00秒)
  • 以前、私が書いた Gawky Auk の中で Emacs のハイライト化について記載しています。 - hi_saito (2005年08月25日 21時45分18秒)

いつか、こちらに転載しておきますが、Emacs でハイライトするには color-mate をインストールしても、gawk (xmlgawk は特に) の関数や変数に対応していませんので、自分で記載するのがベストだと思います。

  • Windows 上の Textpad でも可能です。 - Sashi (2005年08月28日 19時43分13秒)
  • Zeus という Windows のエディタでも可能です。 - jussij (2005年09月01日 23時57分58秒)

対応言語には awk は書かれていませんが、対応可能です。(ただし、Zeus はシェアウェアです){{comment}}

how to merge multiple lines into one line - Jim (2005年08月24日 23時57分06秒)

Tom
Fred
Jim
Bob
Dude
Nerd

というファイル (ファイル名 A) を

Tom Fred Jim Bob Dude Nerd

というファイルにする簡単な方法はありますか?


  • 以下のような方法があります。 - Patrick TJ McPhee? (2005年08月24日 23時58分19秒)
awk -vORS=' ' 1 A

これは以下のものと等価です。

BEGIN { ORS = " " }
{ print }

また、AWK 以外の方法でも可能です。

  • printf() 関数のトリックを用いても可能です。 - trexx (2005年08月25日 00時00分39秒)
(1){
printf "%s ", $0
}                                                                                            
  • "(1)" は必要ありません。 - trexx (2005年08月25日 21時32分52秒)
  • つまり (ITYM)、以下のようなことですね。 - hi_saito (2005年08月25日 21時34分17秒)
{printf "%s%s",s,$0;s=" "}END{print ""}

または

{o=o s $0;s=" "}END{print o}
  • trexx 氏のものは初心者に言うべきでないと思うのですが、いかがでしょう? - hi_saito (2005年08月25日 00時01分59秒)
{
  for ( i = 1; i <= NF; i++ ) {
    STR = sprintf( "%s %s", STR, $NF );
  }
}
END {
  sub( /^ /, "", STR );                                                                      
  printf( "%s\n", STR );
}

と書いてしまう私は未熟なのでしょうか? (長いけど、分かりやすくないですか?)

  • 以下のような方法があります。 - Chris F.A. Johns (2005年08月25日 21時31分10秒)
echo $( cat filename )
  • 以下のような方法があります。 - Ed Morton (2005年08月28日 19時38分25秒)
awk -v RS= '$1=$1' filename
  • 以下のような方法があります。 - Stephane Chazelas (2005年08月28日 19時40分44秒)
paste -sd ' ' - < A
  • 以下のような方法があります。 - John Savage (2005年08月28日 19時40分44秒)
sed ':a;$b;N;s/\n//;ba' file

{{comment}}

Using awk to remove the client port on a netstat listing - Kjell (2005年08月21日 03時59分35秒)

Web Server からの接続で ESTABLISHED のものの FQDN か IP Address 以外を除きたいです。Solaris の netstat は以下のようになっています。

h1.do.com.80 h2.do.com.9081 48799      0 49680      0 ESTABLISHED

つまり、

netstat|grep '^h1.do.com.80'|grep 'ESTABLISHED|tr -s ' '|awk -F' ' '{print $2}'

とすれば、

h2.do.com.9081

が得られます。ただし、ポート No. を除く場合の正規表現が良く分かりません。

^[0-9][0-9][0-9]\.[0-9][0-9][0-9]\.[0-9][0-9][0-9]\.[0-9][0-9][0-9]\.[0-9].*|[A-Z-a-z]*.\.[0-9]

何か良い答えはありますか?


  • cut コマンドを使ってみてはいかがでしょうか? - Sashi (2005年08月21日 04時01分25秒)
netstat|grep '^h1.do.com.80'|grep 'ESTABLISHED|tr -s ' '|awk -F' ' '{print $2}'  | cut -f1-3 -d\.
  • ただし、FQDN が以下のような場合にはどうすればよいでしょうか? - Kjell (2005年08月21日 04時03分10秒)
h1.unit1.department2.adsl-1.dyn.com
  • 以下のような方法があります。 - Chris F.A. Johns (2005年08月21日 04時04分48秒)
netstat | awk '/^h1.do.com.80 .*ESTABLISHED/ { sub(/\.[^\.]*$/,"", $2); print $2 }'

grep を併用すればもっと速くなります。

netstat | grep '^h1.do.com.80 .*ESTABLISHED' | awk '{ sub(/\.[^\.]*$/,"", $2); print $2 }'

awk は不要かもしれません。

netstat | grep '^h1.do.com.80 .*ESTABLISHED' | {
 read a b c
 printf "%s\n" "${b%.*}"
}                                                                                            

netstat の出力が大きくないのであれば、shell を使うのが最速です。

netstat |
  while read -r line
  do
    case $line in
        h1.do.com.80\ *ESTABLISHED)
            set -- $line
            printf "%s\n" ${2##*.}
            ;;
    esac
  done
  • 以下のようなアプローチも可能です。 - William James (2005年08月21日 04時09分08秒)
BEGIN{FS="\.[0-9]+ "}
/^h1.do.com.80 .*ESTABLISHED/ { print $2 }
  • 以下のようなアプローチも可能です。 - Sashi (2005年08月23日 00時31分17秒)
netstat|grep '^h1.do.com.80'|grep 'ESTABLISHED|tr -s ' '|awk -F' ' '{print $2}'  | rev | cut -f2- -d\. | rev

{{comment}}

regex question: match comma not followed by space - David Isaac (2005年08月21日 03時36分19秒)

スペースが後に続かないコンマをフィールドセパレータに使いたいのです。例えば、

this,"but, not that",that

であれば、$1 = this, $2 = "but, not that", $3 = that となります。これは gawk で可能ですか?


  • 以下のようなことを行いたいのでしょうか? - Patrick TJ McPhee? (2005年08月21日 03時37分26秒)
BEGIN { FS = "," }
{
    f[nf = 1] = $1
    for (i = 2; i <= NF; i++)
        if ($i ~ /^ /) f[nf] = f[nf] "," $i
        else f[++nf] = $i
}                                                                                           
  • 問題は、awk がフィールドセパレータを除いた状態でフィールド分割することです。したがって以下のようなものではうまくいきません。 - John DuBois? (2005年08月21日 03時41分30秒)
BEGIN{ FS=",[^ ]"
  • 以下のようなアプローチも可能です。 - Bob Harris (2005年08月21日 03時44分28秒)
echo 'this,"but, not that",that' | awk '
   BEGIN{FS=SUBSEP}
   {
       gsub(/, /,"@#@",$0)
       gsub(/,/,SUBSEP,$0)
       gsub(/@#@/,", ",$0)
       $0 = $0
   }                                                                                        
   {
       for( j=1; j <= NF; j++ ) {
           printf("$%d=`%s` ", j, $j)
       }                                                                                    
       printf("\n");    }                                                                                        
'
  • 以下のようなアプローチも可能です。 - William James (2005年08月21日 03時46分00秒)
BEGIN { FS = "\1" }
{ gsub( /, /, "\2" )
  gsub( /,/, "\1" )
  gsub( /\2/, ", " )
  $0 = $0
  print NF
  for (i=1;i<=NF;i++) print $i
}                                                                                            
  • 個人的には SUBSEP を使うのが最も良さそうと思いますけど、いかがなものでしょうか? もっとも "@#@" は問題を引き起こしそうです。 - hi_saito (2005年08月21日 03時48分08秒)
  • gawk なら gensub() 関数で特殊文字を埋め込むことが簡単にできます。 - John Savage (2005年08月22日 23時37分27秒)
$ cat prog.awk
{ FS=",[^ ]";$0=gensub(/,([^ ])/,",x\\1","g",$0)
for(i=1;i<=NF;i++) print "$"i,$i }
$ echo a,b, c d, e, f,  g,h,i, j,k| gawk -f prog.awk
$1 a
$2 b, c d, e, f,  g
$3 h
$4 i, j
$5 k
  • 上記で改行が "\n" なら以下のようにできます。 - John Savage (2005年08月22日 23時37分27秒)
$ echo a,b, c d, e, f,  g,h,i, j,k| gawk '{gsub(/,[^ ]/,"\n&");
FS="\n,";$0=$0;for(i=1;i<=NF;i++) print "$"i"= "$i}'
$1= a
$2= b, c d, e, f,  g
$3= h
$4= i, j
$5= k                                                                                        

{{comment}}

How to using gawk print String ? - moon (2005年08月21日 02時05分24秒)

gawk の DOS 版を使っています。

c:\temp>gawk "BEGIN { print 4 }"                                                             
4

となりますが、文字列として表示しようとすると、

c:\temp>gawk "BEGIN { print '4' }"                                                           
gawk: cmd. line:1: BEGIN { print '4' }
gawk: cmd. line:1:               ^ invalid char ''' in expression

となってしまいます。

c:\temp>gawk --version                                                                       
GNU Awk 3.1.3
Copyright (C) 1989, 1991-2003 Free Software Foundation.

  • シングルクォートとダブルクォートの振る舞いは問題ないですか? - Bob Harris (2005年08月21日 02時06分52秒)
gawk 'BEGIN{print "string"}'

以下のものならうまくいくのではないでしょうか?

gawk "BEGIN{print \"string\"}"
  • うまくいきました。 - moon (2005年08月21日 02時08分10秒)
c:\temp>gawk "BEGIN{print \"string\"}"                                                       
string
  • DOS 6 なら以下のようになります。 - John Savage (2005年08月21日 02時09分37秒)
C:\>gawk 'BEGIN{print "4+0", 4+0}'                                                           
4+0 4

ただし、これは '<' のような文字が現れるとダメになります。ですから、一番の方法は、ダブルクォートをエスケープする方法です。

  • Cygwin のような UNIX らいくな shell をインストールしてはいかがでしょう? - Bill Marcum (2005年08月21日 02時13分34秒)
  • 以下、Cygwin の話はまとめます。Cygwin は便利なのは間違いないのですが、本物の UNIX 系 OS とは異なる挙動をする場合があることを常に頭に入れておく必要がありそうです。 - hi_saito (2005年08月21日 02時16分43秒)
    • 実は Cygwin を入れているのに、bash を起動していなかった。そのため、shell の展開が変だった。
    • Cygwin は Linux とは全く違うものであり、Linux を動かすなら PC にインストールするべきである。要するに、Cygwin は Windows 上でユーザーが満足するためのものでしかない。

{{comment}}

Is awk right for this? - mtuller (2005年08月21日 01時47分22秒)

システムの情報をデータベースにしようとしており、アプリケーションの情報を以下のような形で保持しています。

Applications:

   Acquisition:

     Version: 117.2
     Last Modified: 2/25/05 1:57 AM
     Location: /Applications/Acquisition.app
     Kind: Native

   Acrobat 6.0.1 Professional:

     Version: 6.0.1
     Last Modified: 10/17/03 5:11 PM
     Get Info String: Adobe?? Acrobat?? 6.0.1, ??1987-2003 Adobe Systems Incorporated. All rights reserved.
     Location: /Applications/Acrobat 6.0 Professional/Acrobat 6.0.1 Professional.app
     Kind: Native

ここでアプリケーションの名前とバージョンだけの情報が必要で他のものは必要ありません。awk でできますか? awk でやるのは適切ですか?


  • awk でやることは正しいです。データベースの配列が分からないものの、以下のようにすれば抽出できます。 - Ed (2005年08月21日 01時49分01秒)
awk -F: 'NF&&!$2{app=$1}$1~/Version/{print app,$2}' file
  • 配列は必要ないのですが、MAC アドレスが特定できるので、mac_address, application_name, application_version がデータベースに挿入できれば、それで十分です。 - mtuller (2005年08月21日 01時52分29秒)
  • PostgreSQL なら xgawk (http://sourceforge.net/projects/xmlgawk) をお勧めします。xgawk は libpq スタイルのインターフェイスを持ち、PostgreSQL ファイルを読むことができます。ただし、書き込むことはできません。MySQL は libdbi を用いて何とかしようとしていますが、うまくいっていません。もちろん、PostgreSQL の psql のような CLI プログラムへ通常の gawk から渡すこともできますが、API を搭載した方がエラー処理などで有利になります。 - Andrew Schorr (2005年08月21日 01時53分56秒)

{{comment}}

Print $PATH entries on separate lines - Sashi (2005年08月21日 01時34分36秒)

GNU Linux 上で以下のようにします。

echo $PATH | gawk -F: "{for (i=1;i<=NF;i++)print $i;}"

すると、":" で区切られた$PATH を行分割して欲しいのですが、NF 回 $PATH が表示されるだけです。何が悪いのでしょうか?


  • ダブルクォートではなく、シングルクォートで区切ります。 - Ed Morton (2005年08月21日 01時35分26秒)
echo "$PATH" | gawk -F: '{for (i=1;i<=NF;i++)print $i}'

ダブルクォートの場合、shell に割り込みをされてしまい、"print $i" を一度 shell が展開してから awk に渡されるため、"print" つまり "print $0" と同じようになってしまいます。

  • awk ではなく、bash や ksh93 を用いて、以下のようにします。 - Chris F.A. Johns (2005年08月21日 01時40分43秒)
printf "%s\n" ${PATH//:/ }

または Bourne shell では以下のようにします。

IFS=:
set -- $PATH
printf "%s\n" "$@"  ## Or: for d do echo $d; done
  • 以下も回答のひとつです。 - Bill Seivert (2005年08月21日 01時42分13秒)
echo "$PATH" | tr ":" "\n"

{{comment}}

テスト - hi_saito (2005年08月21日 01時30分55秒)

テストです。ここには、comp.lang.awk の内容が書かれ、コメントに回答が挿入されます。(その予定)


  • 回答がここに書かれます。 - hi_saito (2005年08月21日 01時31分17秒)

{{comment}}

[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ]


最終更新時間:2007年07月30日 22時13分35秒