awkのパターンとアクション

awkを書く上で重要なパターンとアクションという独特な概念について紹介します。

パターンとアクションとは

awkという言語にはパターン、アクションという2つの重要な概念があります。動作は単純明快で、「パターンにマッチしたレコードに対してアクションを適用する」となります。例えば、パターンとアクションを使った基本的な構文が以下です。

echo foo | awk '$0=="foo" {print "Yes"}'

このコマンドで言うと、$0=="foo" がパターン、 {print "Yes"} がアクションとなります。
※ $0 はレコード全体を表す変数で、この場合はechoされた foo が入っています。

パターンとアクションは基本的に以下のような形式を取ります。

awk 'パターン {アクション}'

また、重要なルールとして以下の2点があります。

  • パターンが省略された時は、全てのレコードに対してアクションを適用する。
  • アクションが省略された時は、マッチしたレコードを出力する。

それぞれ以下の例を見るとよく分かると思います。

$ echo foo | awk '{print "hogehoge"}'
hogehoge
$ echo -e "foo\nbar" | awk '$0=="bar"'
bar

パターンと真偽値

先ほどは「パターンにマッチした」という表現を使いました。実際、$0=="hoge" のように == を等価演算子として評価を行うのは他の言語でも良くあることでプログラマにとって見慣れた光景です。しかし、この評価結果はどのように表されているのでしょうか。実際にprintして見てみましょう。

$ echo foo | awk '{print $0=="foo"}'
1
$ echo bar | awk '{print $0=="foo"}'
0

等価演算子の評価結果は、等価な場合には1を、等価でない場合には0を返しているようです。awkのパターンでは、この評価結果がtruthyな値なのか、falsyな値なのかでマッチしたかどうかを見極めているということです。awkにおいてfalsyな値とは.

  • 数字の0
  • 空文字列

の2つとなります。試しに、これらをパターンとしてprintが行われるかどうかを見てみましょう。

$ echo foo | awk '0 {print "hoge"}'
$ echo foo | awk '"" {print "hoge"}'

いずれの場合も何も出力されません。気をつけなければいけない点としては、あくまで数字の0がfalsyなのであって、文字列の0はfalsyではない点です。

$ echo foo | awk '0"" {print "hoge"}'
hoge

この例では '0"" のようにして、数字の0を文字列に変換しています。文字列の0はtruthyな値のため、今回はhogeが出力されています。
awkには型の概念がないのですが数字と文字列の区別はあり、awkがよしなに判断してくれます。