forkでループ
従来AWKはシングルタスクで、並列処理を行うことはできませんでしたが、最新のgawkには並列処理のための仕組みであるfork()関数が実装されています。このfork()関数が活躍するのは、並列処理を行うサーバーや多重ループ処理のような場面です。ここでは、100万回の処理を10回繰り返す処理にfork()を適用してみます。
通常のAWKであれば以下のように記述します。
BEGIN {
max_i = 10;
max_j = 1000000;
for (i = 1; i <= max_i; i++) {
for (j = 1; j <= max_j; j++) {
print i * j;
}
}
}
このプログラムをloop.awkとして、実際に筆者のサーバーで実行してみました。
$ time gawk -f loop.awk > /dev/null gawk -f loop.awk > /dev/null 7.42s user 0.29s system 76% cpu 10.099 total
約10秒かかっていることが分かります。これを並列処理するには次のようにします。
@load "fork";
BEGIN {
max_i = 10;
max_j = 1000000;
for (i = 1; i <= max_i; i++) {
pid = fork();
if (pid == 0) {
for (j = 1; j <= max_j; j++) {
print i * j;
}
exit 0;
}
}
wait();
}
このfork()関数はPerlなどで用いられているものと同じです。最初のfork()関数の実行でプロセスを生成します。上のプログラムの戻り値である変数pidの値が0の場合は子プロセスを表し、そうでない場合には親プロセスを表します。
作成するプログラムにもよりますが、子プロセスの最後にexit文で終了させるようにしましょう。そうしないと「危険シェル芸」と同じ「fork爆弾」の一種になってしまう可能性があります。実際に、筆者は何度もPCを操作不能にさせた経験があります。
また、ここでは最後にwait()関数を使って、すべての子プロセスの終了を待っていますが、プログラムによっては待つ必要性はありません。
では、このプログラムをfork.awkとして実行してみましょう。
$ time gawk -f fork.awk > /dev/null gawk -f fork.awk > /dev/null 0.58s user 0.02s system 13% cpu 4.381 total
約4秒となり、処理時間は先ほどの半分です。並列処理を行うことにより、実行時間を大幅に短縮できました。
inplace
「inplace」とは元のファイルの置き換えです。sedコマンドの場合には-iオプションまたは--in-placeオプションとして知られています。sedの場合には以下のようにして置き換えることができ、バックアップファイルも作成することができます。
$ cat test.txt USP Magazine $ sed --in-place=.bak 's/Magazine/Mag./' test.txt $ cat test.txt USP Mag. $ cat test.txt.bak USP Magazine
この置き換えとバックアップの機能は便利なため、gawkに対して何度もリクエストがあった機能の1つです。メンテナーのArnold Robbinsは「シェルで代替できるからgawkに実装する必要はない」と言っていましたが、最終的にgawkの拡張機能として実装されました。
このように、gawkにはユーザーからの意見により取り込まれた機能が多くあります。本連載で解説したものでは、正規表現のグループ[a-z]の拡張や組込変数FPATの導入によるCSVファイルへの対応もユーザーからのリクエストです。
さて、今まで説明をしてきたプログラムファイルでは@loadとして拡張機能を読み込んでいましたが、gawkのコマンドラインオプションとして-iオプションでも実行可能です。
$ cat test.txt
USP Magazine
$ gawk '{sub(/Magazine/, "Mag."); print $0}' test.txt
USP Mag.
$ gawk -i inplace '{sub(/Magazine/, "Mag."); print $0}' test.txt
$ cat test.txt
USP Mag.
このままではバックアップファイルを作成することができませんが、バックアップを作成する仕組みもあり、変数INPLACE_SUFFIXに拡張子を指定します。
$ cat test.txt
USP Magazine
$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{sub(/Magazine/, "Mag."); print $0}' test.txt
$ cat test.txt
USP Mag.
$ cat test.txt.bak
USP Magazine
このようにして、sedの置き換えとバックアップの機能も実装されています。
他には?
現在、最新のgawkに関する日本語の書籍は存在していません。ほとんどの書籍はgawk 2.11の時代のものであるとともに、MS-DOS時代のものばかりです。では、こうしたgawkの拡張機能にどのようなものがあるかを知るには、どうすればよいでしょうか。
筆者がよりどころにしているのは、gawkのinfoファイルです。今回紹介した拡張機能は、infoファイルの16章「Writing Extensions for 'gawk'」に、APIを含めてまとめられています。紙面の関係で紹介しきれていない拡張機能があり、サンプルも豊富なので、(残念ながら英語のドキュメントになりますが)興味がある人は見てみてください。
あと、あまり大きな声では言えませんが、米O'Reillyの書籍『Effective awk Programming』はgawkに対応した書籍ですが、実はこのinfoファイルを製本したものです。gawkソースファイルのdocディレクトリにこのデータがあり、以下のようにしてPDF化することができます。
$ cd doc $ make pdf
gawkextlib
gawkのinfoファイルの16.8章には「The 'gawkextlib' Project」というものがあります。これは以前「xmlgawk」や「xgawk」と呼ばれていた、gawkに様々な拡張機能を実装するプロジェクトです。本プロジェクトでは、今も積極的に開発が進められています。具体的には次のような拡張があります。
- GDグラフィックライブラリ拡張
- PDFの拡張
- PostgreSQL拡張
- XML等の構造化テキスト対応
このプロジェクトには私をはじめ日本人の方もいますので、新しいアイデアがあれば提案してみてください。
最後に
長い期間、AWKの講座におつきあいいただき、ありがとうございました。AWKは過去の言語と言われつつも進化し続けているプログラム言語です。使うだけでなく、欲しい機能を提案してみてください。
AWKは簡単なプログラム言語とはいえ、慣れるのに時間がかかりますし、勉強していく中で質問も出てくることでしょう。私が主宰している「日本GNU AWKユーザー会」に参加し、メーリングリストで質問していただいても構いませんし、筆者宛のメールアドレス(hi_saito@yk.rim.or.jp)やTwitter(@hi_saito)に連絡していただければ、どんな内容でも対応できる範囲で回答します。みんなでAWKを覚えて、データ処理を簡単にしていきましょう。
『シェルスクリプトマガジン 2015 February(Vol.22)』は、ただいま絶賛発売中!

『シェルスクリプトマガジン』(毎月25日発売)は日本で唯一のシェルスクリプト総合誌。最新号 2015 February(Vol.22)の特集は「北のDC探訪記!&USP友の会出張一撃勉強会レポ」。友の会の濱田さんが、さくらインターネットの石狩データセンターを取材! 札幌で開催した一撃勉強会のレポートも収録。新連載として、船橋情報ビジネス専門学校の校長先生による「UNIX大好き人間はどう育つ?」がスタート。UNIXの魅力をつづっていただいています。スズラボ通信は、プログラミング初心者へのProcessingのススメ。プログラミングで雪の結晶を降らせます! 他にも好評連載「漢のUNIX」や「ユニケージ開発手法コードレビュー」など見所満載です!
► お求めは、Amazon.co.jp、USP研究所のWebサイト、取り扱い書店まで。
シェルスクリプトマガジン 2015 February(Vol.22)
価格:500円+税
仕様:B5版 64ページ オールカラー
発行人:ユニバーサル・シェル・プログラミング研究所
