編注1:「シェル芸」とは、UNIXシェル(主にbash)のワンライナーを駆使して文字列加工を自由自在に操ることです。また、そのような能力をもつ人をシェル芸人と呼びます。
パターンとアクション
AWKはパターンとアクションを組み合わせるプログラム言語です。日本語で「もし○○だったら、○○をする」という文章のうち、「もし○○だったら」という部分がパターンであり、「○○する」という部分がアクションです注1。このようにパターンとアクションで構成されるAWKの基本文法は直感的であるため、様々な機会で用いられます。これをAWKスクリプトで記述すると以下のようになります。
パターン {アクション}
さて、「パターン」という名前から「正規表現にマッチする」ようなイメージを持たれるかもしれませんが、AWKのパターンは「条件式」そのものであり、その条件式の戻り値による「真偽」にしたがいアクションが実行されます。今回はこのパターンの真偽について深く掘り下げていきます。
AWKはパターンとアクションはそれぞれ省略することができます。パターンを省略した場合には全てのレコードに対しアクションが実行され、アクションが省略された場合にはパターンにマッチしたレコードを表示するという便利な省略を行うことができます。
したがって、パターンの真偽をうまく活用することでAWKらしく簡潔に記述することができるため、AWKの真偽を正しく理解することはとても重要になってきます。
注1 最近2つのWebサービスを連携させるIFTTT (https://ifttt.com/) というサービスがありますが、まさに「パターンとアクション」で構成されている例と言えるでしょう。
AWKの真偽って何?
さて、AWK の真偽はどのように判定されているのでしょうか。AWKにはTRUEやFALSEといったブール値というものは存在しません。そこで、AWKは以下のようにして判定しています。
- 数字の0(ゼロ)は「偽」となります。
- 空の文字列は「偽」となります。
- 上記以外は全て「真」となります。
これだけです。AWKには「型」がないにも関わらず、数字とか文字列とか書かれているのは不思議に思われるかもしれませんが、故意に型を変換することで真偽を自在に操ることができるのです。
では、実際に試してみましょう。前述のようにアクションがない場合にはレコードをそのまま表示しますので、「数字の0」(「文字列の"0"」ではない点に注意してください)をパターンに指定してみます。
$ echo "foo" | awk '0'
何も表示されませんね。では、「数字の4」を入れてみましょう。
$ echo "foo" | awk '4' foo
数字の1でも何でも数字の0以外であれば構わないのですが、他の文字との読み違えを防ぐため、AWK界隈では数字の4が好まれる傾向にあります。では、文字列の場合はどうでしょうか。
$ echo "foo" | awk '"bar"' foo
パターンが文字列"bar"というのはとても変ですが、先ほど述べたとおり、空の文字列ではないため「真」となり、パイプで渡されたレコードがそのまま表示されています。この文字列"bar"は正規表現ではなく文字列として扱われる点に注意してください。
AWKの真偽はこれが全てです。簡単ですが、さらに理解を深めることで様々な条件分岐をエレガント注2に行うことができます。
注2:AWK使いは「エレガント」という言葉を好んで使います。
比較演算子、マッチング演算子
AWKにはC言語のような比較演算子があり、数値も文字列も同様に扱うことができます。例えば以下のようなものです。
$ echo "foo" | awk '$0 == "foo"' foo
さて、この比較演算子は何を返しているのでしょうか。print文で確かめてみましょう。
$ echo "foo" | awk '{print $0 == "foo"}' 1 $ echo "foo" | awk '{print $0 != "foo"}' 0
つまり、比較演算子の真は数字の1で、偽は数字の0を返しています。
さらに、AWKには正規表現にマッチするかどうかを判定するマッチング演算子もあります。こちらも見てみましょう。
AWKの中で単独で「/」で囲まれた正規表現が用いられた場合には「$0 ~」が省略されたものと見なされます注3ので、以下のように記述することもできます。
$ echo "foo" | awk '/foo/' foo
さて、どのように真偽の判定をしているのか見てみましょう。
$ echo "foo" | awk '{print /foo/}' 1 $ echo "foo" | awk '{print !/foo/}' 0
この記法を{print "foo"}のつもりで使ってしまって、うまく動作しなかった経験がある方もいらっしゃると思いますが、前述のように「$0 ~」が省略されているため、戻り値は数字の0または数字の1なのです。このように、比較演算子やマッチング演算子は数字の0または数字の1で判定されていることが分かります。
注3:この省略はパターンのみに有効だと思われている方が多いのですが、AWKの組込関数で使われる場合以外の全てで有効な省略です。