多次元配列
AWKには多次元配列がありません。しかし、これを補う、とても便利な機能が用意されています。
BEGIN { names[1, 1] = "Fuji Apple"; names[1, 2] = "Tsugaru Apple"; names[2, 1] = "Blood Orange"; names[2, 2] = "Mikan"; for (i = 1; i <= 2; i++) { for (j = 1; j <= 2; j++) { print i, j, names[i, j]; } } }
このように疑似的な多次元配列を用いることができます。この仕組みは次のように説明できます。配列のインデックスをカンマで区切ると、インデックスの中のカンマは8進数で「\034」に展開されます。この「\034」ですが通常のテキストファイルには出現しないであろう文字を作者たちが選んでいます。また、スペースは連接として扱われます。つまり、次のリストと同じです。
BEGIN { names[1 "\034" 1] = "Fuji Apple"; names[1 "\034" 2] = "Tsugaru Apple"; names[2 "\034" 1] = "Blood Orange"; names[2 "\034" 2] = "Mikan"; for (i = 1; i <= 2; i++) { for (j = 1; j <= 2; j++) { print i, j, names[i, j]; } } }
このようなトリックを使うことで、AWKでも疑似的に多次元配列を用いることができます。
GNU AWKでは本当の多次元配列を扱うことができるようになったため、このようなトリックを用いる必要はありません。ただ、本稿では説明を省きます。
配列が空かどうか?
AWKでは、あるインデックスを持つ配列が、空なのかどうかを検査する場合、どうすると思いますか? 次に挙げるリストのようにしてしまうと、検査した配列を自動的に生成してしまいます。ただし、実際に生成されたかどうかについては、GNU AWKを使わない限り、AWKそのものに変数をダンプする機能はないので、分かりにくいかもしれません。
BEGIN { value_of["Apple"] = 100; value_of["Orange"] = 200; value_of["Banana"] = 300; if (value_of["Kiwi"] == "") { print "Kiwi is not found."; } }
そこで、配列の検査を行う際、次のようにすると、検査した配列を作成せずに済みます。
BEGIN { value_of["Apple"] = 100; value_of["Orange"] = 200; value_of["Banana"] = 300; if ("Kiwi" in value_of) { print "Kiwi is not found."; } }
上述の方法では、連想配列value_of["Kiwi"]を作成せずに検査しています。少し特殊な使い方ですが、連想配列としての色合いが濃い使用方法といえます。
シェル芸で配列
シェル芸編注1で配列を用いるケースはたいへん限られています。最も頻繁に使われるのは重複行を1つにするものです(次の例はzshの場合。bashではechoに-eオプションを指定)。
$ echo "aaa\nbbb\naaa" | awk '!a[$0]++' aaa bbb
連想配列aのインデックスに$0(行)を入れて加算しています。それを否定しているわけですから、連想配列a[$0]が加算されない最初のものだけを表示します。その結果として重複行が1つになるわけです。
これを普通のシェル芸で行う場合はsortコマンドとuniqコマンド編注2を用います。
$ echo "aaa\nbbb\naaa" | sort | uniq aaa bbb
この場合にはsortコマンドをパイプの間に挟んでしまうため、sortコマンドが終了するまで次のuniqには結果が渡されません。しかし、AWKの連想配列を用いた場合には、結果を待つことなく逐次出力されるため、より高速に処理することができます。
それとは逆に、重複している行だけを表示するには、次のように入力します。
$ echo "aaa\nbbb\naaa" | awk 'a[$0]++ == 1' aaa
からくりは同じで、連想配列a[$0]を加算して1の場合、つまり、重複が現われた時だけ表示する、という仕組みになっています。
これをシェル芸で行うには、uniqコマンドの-d(Duplicate)オプションを用います。
$ echo "aaa\nbbb\naaa" | sort | uniq -d aaa
こちらも処理行数が多い場合にはAWKで対応する方がより高速でしょう。
編注1:「シェル芸」とは、UNIXシェル(主にbash)のワンライナーを駆使して文字列加工を自由自在に操ることです。また、そのような能力をもつ人をシェル芸人と呼びます。
編注2:sortコマンドは並べ替え(ソート)を行うコマンド。uniqコマンドは重複するデータを削除するコマンド。
さいごに
今回で通常のAWKを用いた処理の説明は終了です。いかがでしたか。AWKを単に特定のフィールドを取り出すcutコマンドの代用で使っていた方も、きっと様々な処理を行えるようになったことでしょう。
さて、次回からは(何回になるか考えていませんが)、GNU版AWKのgawkについて説明したいと思います。gawkはLinuxのほとんどのディストリビューションに標準でインストールされているため、ひょっとすると皆さんが使われているAWKもgawkなのかもしれません。筆者の環境であるFedoraでは、/bin/awk は/bin/gawkのシンボリックリンクになっています。
現在出版されている書籍のほとんどはMS-DOSのjgawk時代、つまりgawk Ver.2.11.1時代のものが元になっていますが、最新のgawkはVer.4.0.1となり大幅にパワーアップしています。おそらく本邦初となる、日本語の最新gawk解説になりますので、どうぞご期待ください。
『USP MAGAZINE』は日本で唯一のシェルスクリプト総合誌(毎月25日発売)。最新号 2014 October(Vol.18)はよりインパクトのあるロゴデザインにリニューアル! 巻頭特集は「インフラエンジニアのおしごと」。「サーバー運用お助けTips」の濱田さんが、冒頭と連載を特別執筆。キーワードは“がんばらない運用”です。また、6月に開催されたインフラエンジニア向けのイベント「July Tech Festa」のレポート記事も収録。そして、本連載AWK処方箋は今号から「GNU AWK 処方箋」としてスタート! GNU拡張で便利になった点を解説します。他にも「ユニケージ開発手法 コードレビュー」や「Haskellでやってはいかんのか?」など好評連載中です!
► お求めは、Amazon.co.jp、USP研究所のWebサイト、取り扱い書店まで。
USP MAGAZINE 2014 October(Vol.18)
価格:500円+税
仕様:B5版 64ページ オールカラー
発行人:ユニバーサル・シェル・プログラミング研究所