Edited at

AWK のフィールドセパレータの真実

More than 1 year has passed since last update.

という内容を社内 SNS っぽいところに投稿したところ、次のようなツッコミがありました。


大抵の環境では gawk が入っているので区切り文字に正規表現が指定できるようですね。

cat hoge.log | awk -F',+' '{print $2}'


なん・・だと・・

そこ、正規表現だったの??

じゃあ awk -F'.' とか、超使い方間違えていたの? 死ぬの?


man awk 曰く(Fields の辺り)。


If FS is a single character, fields are separated by that character.

If FS is the null string, then each individual character becomes a separate field.

Otherwise, FS is expected to be a full regular expression.

In the special case that FS is a single space, fields are separated by runs of spaces and/or tabs and/or newlines.


意訳。


  • 単一の文字なら、フィールドはその文字で句切られる

  • 空文字列なら、それぞれの文字が別々のフィールドになる(1文字ずつのフィールドになる)

  • それ以外なら正規表現になる

  • 特殊なケースで、単一のスペースなら、空白/タブ/改行、のいずれかで区切られる

なるほど。

$ cat <<EOS> hoge.txt

aaa.123 xxx
bbb.456 yyy
ccc.789 zzz
EOS

1文字なら只の文字。

$ cat hoge.txt | awk -F. '{print $2}'

123 xxx
456 yyy
789 zzz

2文字以上なら正規表現。

$ cat hoge.txt | awk -F'[0-9]+' '{print $1}'

aaa.
bbb.
ccc.

空文字なら文字ごとに区切り。

$ cat hoge.txt | awk -F '' '{print $6}'

2
5
8

単一のスペースなら空白/タブ/改行。

$ cat hoge.txt | awk -F ' ' '{print $1}'

aaa.123
bbb.456
ccc.789

最後のケースはレコードセパレータも変えるとわかりやすい。

$ cat <<EOS> hoge.txt

aaa
bbb
ccc
.
123 456 789
.
xxx
yyy
zzz
EOS

$ cat hoge.txt | awk -F ' ' -v RS=. '{print $2}'
bbb
456
yyy


awk -F'.' は無事だった・・よかった。