はじめに
GNU awk(gawk)の使い方を説明します。ここでは単にawkといいます。
awkはテキスト処理のために設計されたプログラムです。
考え方
awkは1行毎に処理を行います。ファイルの最後まで処理をしたら終了します。
パターン(pattern)にマッチしたときに処理(action)を行います。
pattern { action }
行毎の処理前、後におこなう処理は次のように指定できます。
BEGIN { action }
END { action }
sample
lsで表示される情報を空白で区切った列を抜き出します。
lsした結果です。
$ ls -lsa | head
合計 252
4 drwxr-xr-x 22 user user 4096 10月 5 02:09 .
4 drwxr-xr-x 3 root root 4096 5月 7 23:55 ..
24 -rw------- 1 user user 24468 10月 5 02:09 .ICEauthority
4 -rw------- 1 user user 201 10月 5 02:09 .Xauthority
4 drwx------ 3 user user 4096 8月 28 22:08 .anthy
4 -rw-r--r-- 1 user user 177 5月 7 23:51 .apport-ignore.xml
32 -rw------- 1 user user 31623 10月 5 02:01 .bash_history
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 3647 5月 7 23:48 .bashrc
lsの結果をpipeでawkに繋げて6列を表示する例です。
$ ls -lsa | awk '{ print $6 } ' | head
4096
4096
24468
201
4096
177
31623
220
3647
6列は$6で参照できます。
$6="" とすることで6列を削除します。
$ ls -lsa | awk '{ $6=""; print $0 }' | head
合計 264
4 drwxr-xr-x 22 user user 10月 14 22:37 .
4 drwxr-xr-x 3 root root 5月 7 23:55 ..
28 -rw------- 1 user user 10月 14 22:30 .ICEauthority
4 -rw------- 1 user user 10月 14 22:30 .Xauthority
4 drwx------ 3 user user 8月 28 22:08 .anthy
4 -rw-r--r-- 1 user user 5月 7 23:51 .apport-ignore.xml
36 -rw------- 1 user user 10月 14 10:19 .bash_history
4 -rw-r--r-- 1 user user 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 5月 7 23:48 .bashrc
次に"bash"を含む行を表示する例です。
$ ls -lsa | awk '/bash/ { print $0 } ' | head
32 -rw------- 1 user user 31623 10月 5 02:01 .bash_history
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 3647 5月 7 23:48 .bashrc
パターンに/bash/を指定します。現在の行は$0で参照します。
次に"bash"を含む行の6列を合計します。
$ ls -lsa | awk 'BEGIN {v=0} /bash/ {print $0; v+=$6} END {print v}'
32 -rw------- 1 user user 31623 10月 5 02:01 .bash_history
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 3647 5月 7 23:48 .bashrc
35490
BEGINでvを初期化します。v+=$6で6列を加算します。ENDでvを表示します。
フィールドの区切りのデフォルトは空白です。
次のようにして区切り文字が変更できます。
カンマに変更する例です。
-F オプションで指定する例
$ cat data.txt
taro,20,kanagawa
jiro,19,tokyo
saburo,16,chiba
$ cat data.txt | awk -F, '{ print $1 }'
taro
jiro
saburo
FSで指定する例
$ cat data.txt | awk 'BEGIN { FS="," } { print $2 }'
20
19
16
printで標準出力に文字列を表示できます。
次に例を示します
$ awk 'BEGIN { print "a","b" }'
a b
$ awk 'BEGIN { print "a""b" }'
ab
$ awk 'BEGIN { print "a" "b" }'
ab
$ awk 'BEGIN { OFS=";"; print "a","b" }'
a;b
文字列を","で繋げると文字列の間にseparatorが出力されます。
separatorはOFS変数に値を設定することで変更できます。
OFSの初期値は空白" "です。
printfを使うとC Language の printfと類似の方法で表示できます。
改行コードを明示する必要があります。
$ ls -lsa $HOME | head | awk '{ printf "%x %d\n", NR, NR }'
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
a 10
script file
awk programをファイルに保存してbash scriptのように利用できます。
# !/usr/bin/awk -f
BEGIN {
print "Hello"
}
{ print }
実行します。
$ ls -lsa $HOME | ./test.awk | head
Hello
合計 260
4 drwxr-xr-x 22 user user 4096 10月 14 10:19 .
4 drwxr-xr-x 3 root root 4096 5月 7 23:55 ..
28 -rw------- 1 user user 24850 10月 11 08:04 .ICEauthority
4 -rw------- 1 user user 201 10月 11 08:04 .Xauthority
4 drwx------ 3 user user 4096 8月 28 22:08 .anthy
4 -rw-r--r-- 1 user user 177 5月 7 23:51 .apport-ignore.xml
36 -rw------- 1 user user 36578 10月 14 10:19 .bash_history
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
Built-in Variables
awkには定義済みの変数があります。
次に定義済みの変数一覧を示します。
name | description |
---|---|
$0 | 現在処理中の行 |
$1 | 現在の行に含まれる1番目のフィールド |
$N | 現在の行に含まれるN番目のフィールド |
FS | Field Separator ; 入力のフィールド区切り |
RS | Record Separator ; 入力の改行コード |
OFS | Output Field Separator ; 出力のフィールド区切り |
ORS | Output Record Separator ; 出力の改行コード |
NR | Number of Records ; 行番号 |
NR
NRはBEGINで0, 各行で行番号、ENDで行数になります。
# !/usr/bin/awk -f
BEGIN {
print "BEGIN NR", NR
}
{
print NR
}
END {
print "END NR", NR
}
$ ls -lsa $HOME | head | ./test.awk
BEGIN NR 0
1
2
3
4
5
6
7
8
9
10
END NR 10
制御構造
# !/usr/bin/awk -f
BEGIN {
print "if"
i = 10
if (i == 10) {
print "i == 10"
} else if (i == 20) {
print "i == 20"
} else {
print "else"
}
print
print "for"
for (i=0; i<3; i++) {
print i
}
print
print "while"
i = 3
while (i--) {
print i
}
print
}
$ ./test.awk
if
i == 10
for
0
1
2
while
2
1
0
Array
行をまたがった処理をする場合、読み込んだ行をArrayに保存しておきます。
Arrayの使い方を説明します。
# !/usr/bin/awk -f
{
a[NR] = $0
}
END {
for (i=1; i<=NR; i++) {
print a[i]
}
}
NRは最初の行で1となります。最後の行で行数となります。
よってfor文は1から始まってNで終わっていることに注意してください。
$ ls -lsa $HOME | head | ./test.awk
合計 260
4 drwxr-xr-x 22 user user 4096 10月 14 10:19 .
4 drwxr-xr-x 3 root root 4096 5月 7 23:55 ..
28 -rw------- 1 user user 24850 10月 11 08:04 .ICEauthority
4 -rw------- 1 user user 201 10月 11 08:04 .Xauthority
4 drwx------ 3 user user 4096 8月 28 22:08 .anthy
4 -rw-r--r-- 1 user user 177 5月 7 23:51 .apport-ignore.xml
36 -rw------- 1 user user 36578 10月 14 10:19 .bash_history
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 3647 5月 7 23:48 .bashrc
配列のサイズはlengthで取得できます。
$ ls -lsa | head | awk '{ a[NR] = $0 } END { print length(a) }'
10
パターンマッチ
~(tidle)と//を使うことで文字列が正規表現にマッチしたかどうかを確認できます。
$ ls -lsa | head
合計 264
4 drwxr-xr-x 22 user user 4096 10月 14 22:37 .
4 drwxr-xr-x 3 root root 4096 5月 7 23:55 ..
28 -rw------- 1 user user 25232 10月 14 22:30 .ICEauthority
4 -rw------- 1 user user 201 10月 14 22:30 .Xauthority
4 drwx------ 3 user user 4096 8月 28 22:08 .anthy
4 -rw-r--r-- 1 user user 177 5月 7 23:51 .apport-ignore.xml
36 -rw------- 1 user user 36578 10月 14 10:19 .bash_history
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 3647 5月 7 23:48 .bashrc
$ ls -lsa | head | awk '{ if($0~/23/) print }'
4 drwxr-xr-x 3 root root 4096 5月 7 23:55 ..
28 -rw------- 1 user user 25232 10月 14 22:30 .ICEauthority
4 -rw-r--r-- 1 user user 177 5月 7 23:51 .apport-ignore.xml
4 -rw-r--r-- 1 user user 220 5月 7 23:48 .bash_logout
4 -rw-r--r-- 1 user user 3647 5月 7 23:48 .bashrc
$ ls -lsa | head | awk '{ if($0~/root/) print }'
4 drwxr-xr-x 3 root root 4096 5月 7 23:55 ..
Arrayを使ってパターンマッチした行とその次の行を表示する例です。
# !/usr/bin/awk -f
{
a[NR] = $0
}
END {
for (i=1; i<=NR; i++) {
if (a[i]~/bss|data/) {
print a[i]
print a[i+1]
}
}
}
実行ファイルからrodata / data / bss sectionの情報を取り出します。
$ readelf -S ./a.out | ./test.awk
[15] .rodata PROGBITS 0000000000400580 00000580
0000000000000004 0000000000000004 AM 0 0 4
[24] .data PROGBITS 0000000000601028 00001028
0000000000000010 0000000000000000 WA 0 0 8
[25] .bss NOBITS 0000000000601038 00001038
0000000000000008 0000000000000000 WA 0 0 1