斉藤 博文 [著] 2014/10/27 14:00
このエントリーをはてなブックマークに追加

1 2 →

 今回からGNU AWKの拡張について説明していきます。AWKは便利なツールですが、今まではある程度複雑なことを行おうとするとPerlやRubyなど他のスクリプト言語に頼っていた方も多かったと思います。GNU拡張によりAWKは大幅に拡張され、様々な用途での利用されることが期待されています。今回から数回に渡りGNU AWKで便利になった点を中心に解説していきます。

最新版のGNU AWKを入手

 GNU AWKのコードは現在GNU Savannahのgitリポジトリにあります。したがって、gitコマンドを用いて最新版を入手することができます。

$ git clone 'git://git.savannah.gnu.org/gawk.git'

 上記コマンドを実行するとカレントディレクトリにgawkという名前のディレクトリが作成され、その中にGNU AWKのmasterコードがダウンロードされます。

 これをビルドするには以下のようにします。

$ cd gawk
$ ./configure && make

 &&は前のコマンドの戻り値が0、つまりコマンドが成功すれば次のコマンドを実行するという意味です。

 インストールするにはrootになり、以下のコマンドを実行します。

# make install

 インストール先はconfigureスクリプト実行時やmakeコマンド実行時に指定できますが、デフォルトでは/usr/local/binになります。これで最新のGNU AWK がインストールされます。これから最新のGNU AWKについての解説をしていきますが、ディストリビューションごとに用意されているGNU AWKと異なる場合がありますので、ご注意ください。

正規表現の拡張

 最初に紹介するのは正規表現の拡張です。アルファベットまたは数字の連続する5個の文字列にマッチさせようとすると、従来は大変でした。

[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]

 もちろん、これはこれで分かりやすいのですが、もっと数が多くなってくると読みづらいものになってきてしまいます。もっとも正規表現は決して読みやすいものではありませんが、GNU AWKでは個数を指定することができます。

[a-zA-Z0-9]{5}

 スッキリしましたね。少し古いGNU AWK でも起動時のオプション(--re-interval)でこのような表現を使うことは可能でしたが、最新のGNU AWKではデフォルトで使うことが可能になりました。随分前からオプションで指定できたのですが、標準実装されるまでに時間がかかったのはメンテナーの慎重さの表れだと思います。

 また、この[a-zA-Z0-9]のような集合を表す正規表現も拡張されています。このようにアルファベットと数字を表す正規表現の集合は以下のようになります。

[[:alnum:]]

 角括弧が二重になっている点に注意してください。man ページの正規表現では[:alnum:]となっていますが、manページに記述されている部分は中身のa-zA-Z0-9だけであり、実際に正規表現として用いる場合には、上記のように角括弧を二重に記述します。メーリングリストに投げられる質問でも時々見かけます。

 GNU AWKではさらに誤解を招くような正規表現に少し手を入れています。

$ echo "abc" | LC_ALL=en_US gawk '/[A-Z]/'
abc

 abcが大文字というのは変ですよね。これは使用環境の言語設定によっては[A-Z]が大文字だけの集合を表現しないために起こりうるもので、grepやsedコマンドでも同様の問題があります。これに対してGNU AWKでは[a-z]は小文字だけの集合、[A-Z]は大文字だけの集合を示すように工夫してあります。GNU AWKのメンテナーであるArnold Robbinsも「これで面倒な質問に答える必要がなくなった」というようなニュアンスで紹介していました。GNU全体の中でもgrepコマンドやsedコマンドもどうしていくかが話題となっており、今後のAWKの動向が注目されています。

 この場合には、先ほど紹介した正規表現集合[:upper:]で回避することもできます

$ echo "abc" | LC_ALL=en_US gawk '/[[:upper:]]/'
(何も出力されない)

 GNU AWKで拡張された正規表現は多いため、とてもこの紙面で紹介しきれるものではありません。manページやinfoコマンドで調べてみてください。

RSの正規表現対応、RTの追加

 組込変数RSは通常のAWKでは文字列しか指定することができませんでした。そのため、正規表現でレコードを分割したくてもできませんでしたが、GNU拡張により組込変数RSに正規表現を用いることが可能になっています

 実際に組込変数RSに正規表現を用いると便利な場合はどのようなものがあるでしょうか? それは構造化されたテキストファイル、例えばHTMLやXMLのようなものです。こうしたテキストファイルは改行ではなくタグにより区切られます。

 例えば、Webページのタイトルを抽出する一行野郎は、以下のように簡単に記述することができるようになります。

$ curl -s 'http://gauc.no-ip.org/awk-users-jp/' | \
  gawk -v RS='</?title[ ]?[^>]*>\r?\n?' 'NR==2'
AWK Users JP :: 日本の AWK ユーザのためのハブサイト

 さて、正規表現で分割すると、実際に用いられた区切りは何だったかを知りたくなります。GNU AWKでは、この解として組込変数RTがあります。組込変数RTには組込変数RSで区切られた際の区切られたレコードセパレーターの文字そのものが格納されます

$ curl -s 'http://gauc.no-ip.org/awk-users-jp/' | \
  gawk -v RS='</?title[ ]?[^>]*>\r?\n?' '{print RT}'
<title>
</title>

 つまり、先ほどのWeb ページのタイトルを抜き出すもので使われた組込変数RSは<title>と</title>であったことが分かります。

 また、ここでは詳細を紹介しませんが、ファイル全体を1つのレコードとして扱うため、組込変数RSに¥0を使うこともできます。これも構造化されたテキストを扱う布石の一つでしょう。また、組込変数RS、RTを使えばWebページのCGIでPOSTされた内容も扱えるようです。


1 2
→
INDEX
正規表現がもっと使える! 直感的にも使いやすくなった最新GNU AWKの拡張機能を知る
Page1
最新版のGNU AWKを入手
正規表現の拡張
RSの正規表現対応、RTの追加
length関数の扱い
引数版 match関数
連想配列のfor ~ inでの呼び出し
まとめ
こちらの関連記事もおすすめです

プロフィール
斉藤 博文 サイトウヒロフミ

最初にAWKと出会ってから○十年、AWKの魅力に取りつかれ、勢い余って「日本 GNU AWKユーザー会」を立ち上げています。会としてOSCなどのイベントにも出展しつつ、GNU AWKの開発も手伝っています。「USP友の会」では幹事役ですが、「シェル芸勉強会」にはほぼ毎回参加して一緒に勉強しています。


記事へのコメント・トラックバック機能は2011年6月に廃止させていただきました。記事に対する反響はTwitterやFacebook、ソーシャルブックマークサービスのコメントなどでぜひお寄せください。