awk 備忘録
awkとは
awkは、Linux上のファイルに対して、"行ごとに"何らかの処理を行うためのプログラミング言語。
"行ごとに"処理を行うため、行指向プログラミングと呼ばれる。
csvファイルを扱うときによく使われる。
awkを操作するために知っておくべき10のこと
awkを操作するために知っておくべき10のことを、順に列挙する。
今回は以下のtest.datを操作対象とする。
$ vi test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7
その1:awkコマンドは"awk -f awkファイル データファイル"で実行する。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test01.awk # 各行を表示させるawkプログラム { print $0 } $ awk -f test01.awk test.dat # test.datに対してtest01.awkを実行 tea 10 2013/5/3 tea 5 2012/9/10 cake 7 2011/7/7 $ awk '{print $0}' test.dat # 直接''内にawkを記述することもできる tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7
その2:コメントは#で書く
$ vi test02.awk # ここはコメントです。
その3:{}内は各行で実行される。ただし、{}の直前に条件があれば、それを満たす行のみ実行される。BEGIN{}内は最初に1度だけ、END{}内は最後に1度だけ実行される。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test03.awk BEGIN{ # 最初に実行 } { # 各行で実行 } NR<2 { # 行番号が2未満のとき実行 } END{ # 最後に実行 }
その4:表示はprintとprintf(フォーマッタを用いたprint)を用いる。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test04.awk BEGIN{ # 最初にbeginを表示 print "----begin----" } END{ # 最後にendを表示 print "-----end-----" } $ awk -f test04.awk test.dat ----begin---- -----end-----
その5:各行が(デフォルトで)スペースかタブ区切りでフィールドに分割される。n番目のフィールドは$nで取得できる。$0で全フィールドを取得できる。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test05.awk { print $1 # 1番目の要素を表示 } $ awk -f test05.awk test.dat tea tea cake
その6:NRはレコード番号(処理中の行数)、NFでフィールド数、FSは区切り文字を表す。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test06.awk BEGIN{ FS="/" # 区切り文字に/を指定 } { print NR ":" NF # 各行の行数と最後の要素を表示 } $ awk -f test06.awk test.dat 1:3 2:10 3:7
その7:組み込み関数が使える。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test07.awk { # rand(): 0-1の乱数を発生させる, int(): 数値の整数部分を返す printf("%f %d ", rand(), int($2/2)) # substr(): 部分文字列を返す, length(): 文字数を返す print substr($3,6,length($3)) } $ awk -f test07.awk test.dat 0.237788 5 5/3 0.291066 2 9/10 0.845814 3 7/7
その8:制御構文が使える。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test08.awk { printf("%2d:", NR) # 2番目の要素の数だけ*を表示させる for (i=0; i<$2;i++) { printf("*") } printf("\n") } $ awk -f test08.awk test.dat 1:********** 2:***** 3:*******
その9:配列が使える。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test09.awk BEGIN{ str[1]="sum" str[2]="ave" print str[1] } { sales[$1] += $2 # 文字列も配列のインデックスに指定できる } END { for (name in sales) { print name ":" sales[name] } } $ awk -f test09.awk test.dat sum cake:7 tea:10 ice:5
その10:関数が定義できる。
$ cat test.dat tea 10 2013/07/10 tea 5 2012/9/10 cake 7 2011/7/7 $ vi test10.awk function profit(n) { return n * 10 } { printf("%-4s %3d\n",$1,profit($2)) } $ awk -f test10.awk test.dat tea 100 ice 50 cake 70