読者です 読者をやめる 読者になる 読者になる

Tech Blog

Information Technology / Machine Learning / Data Analysis / Big Data / System Integration

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