コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

利用者:Mpsuzuki/sandbox8

AWK
テンプレートを表示


AWKオーク[1][2][3])は、プログラミング言語の一つ。 テキストファイル、特に空白類(スペースの他、タブなど)やカンマなどで区切られたデータファイルの処理を念頭に置いた仕様となっているが、一般的なプログラミングに用いることも可能である。UNIX上で開発された。

概要

[編集]

AWKは、ベル研究所におけるUNIX開発の過程で、sedgrepのようなテキスト処理ツールに演算機能を持たせた拡張ツールとして1977年[4]に開発された。UNIX上のシェルスクリプトの中で使うことを想定していたため、たとえば sortなどのコマンドの存在を前提としており[4]、これに対応する組み込みのソート関数などは持っていない[注釈 1]。これはAWKをUNIX以外の環境で用いる場合の難点の一つである。

AWKは簡単なスクリプトを記述することで効率的にテキストファイルを処理することが目的であったため、当初はそれほど多くの機能は無かった。普及するにつれ、さまざまな処理をAWKで実行したいと考えるユーザーが増え、テキスト処理だけに留まらず、大規模なプログラムに使う例もあらわれた。それらの用途の希望に応えるよう改修が加えられ、汎用のプログラミング言語と比べても遜色が無いほどの機能を持つようになった[注釈 2]。 1985年に完成した版は、System V Release 3.1の一部ともなった[4]。一方、本来のテキスト処理用ツールとしても扱いやすく、現在でもCSV形式のファイルを簡易に処理する、などの目的で広く使用されている。

「AWK」という名称は、開発者であるアルフレッド・エイホピーター・ワインバーガーブライアン・カーニハンの3人の苗字の頭文字を取って付けられたものであるが、カーニハンは「エー・ダブリュー・ケー」ではなく「オーク」と読むとした。[注釈 3]。 また、全て小文字でawkとした場合、Unix系OSないしPlan 9における、AWKのインタプリタ処理系プログラム自体(他の多くのコマンドと同じく全て小文字である)を指してそうしていることがある。

AWKの文法

[編集]

本章では、『プログラミング言語AWK』に従い、nawk以降の文法について述べる。より古いoawkはこれと異なる部分があるので注意されたい。

基本構成

[編集]

AWKのスクリプトは、パターンとアクションの組を並べた形になっている。 実行を開始すると、まずBEGINパターンのアクションを実行する。 以降、入力を読み込んでは、レコード分離文字(既定では改行)までを1レコードとし、ユニット分離文字(既定では連続するスペースまたは水平タブ)に従ってフィールドに分割してから、レコードがパターンにマッチするかを調べ、パターンにマッチしたらそのパターンに対応するアクションを実行する。 一致するパターンが複数ある時は、該当するアクションが上から順に全て実行される。これを入力が尽きるまで繰り返す。入力が尽きたら、ENDパターンのアクションを実行し、終了する。すなわち、テキストストリームをシーケンシャルに読み込み、入力されるテキストストリームをレコードセパレータ毎に区切り、1行毎にスクリプトに記述されたアクションを順次実行する。

ファーストクラスデータ型は、数値(全て倍精度浮動小数点型で扱われる)と文字列である。

他に文字列をキーとした連想配列があるが、連想配列はファーストクラスではなく関数の返戻値にできないなどデータというよりは、配列変数という変種の変数があるといったような扱いである。連想配列の中身(要素)を連想配列にすることはできないため、ループするようなデータ構造を作ることは不可能。連想配列のキーに数値を使うと、文字列に変換したものがキーとなる。 arr[x, y]のようにして多次元配列のように見えるアクセスもできるが、実際には各次元を必要であればまず文字列化した後に、グローバル変数SUBSEPの文字列(デフォルトではU+001C <control-001C>)をセパレータとして連結した文字列をキーとしてアクセスする。

スクリプトの基本構成は次のようになる。

BEGIN {
    開始時処理
}
パターン1 {
    アクション1
}
パターン2 {
    アクション2
}
……
# コメント
END {
    終了時処理
}

BEGINENDアクションは必須ではない。

例として、テキストファイル内の全ての行のうち、空行の数と「林檎」・「りんご」または「リンゴ」という文字列を含む行の数をそれぞれ出力するAWKプログラムを示す。

BEGIN {
    # 行の個数を表わす変数を宣言・初期化
	blank_line = 0
	bol_apple = 0
}

/^$/ {
	++blank_line
}

/(林檎|りんご|リンゴ)/ {
	++bol_apple
}

END {
	print "空行は" blank_line "行です。"
	print "「林檎」・「りんご」または「リンゴ」という文字列を含むのは" bol_apple "行です。"
}

なお、AWKでは、まだ代入されていない変数は暗黙のうちに0または""で初期化されると仮定してよいので、上の例でのBEGINブロックは必須ではない。

パターンには以下のように開始と終了を定義するパターンもある。

/開始パターン/,/終了パターン/ {
    アクション
}

例えば、以下のようなプログラムは、「<script>」を含む行から「</script>」を含む行まで(その行自身を含む)の間、指定されたアクションが実行する(この場合は単に行全体を出力する)。

/<script>/,/<\/script>/ {
    print $0;
}

変数

[編集]

AWKの特徴の一つとして変数が型を持たないことが挙げられる。変数宣言が不要で、プログラム中で使用される変数は暗黙のうちに初期化される。このため、未定義変数や未初期化変数を参照することによるエラーはAWKには存在しない。

AWKは算術演算のような数値を必要とする文脈では暗黙に値を数値に変換し、逆に文字列を必要とする場合には文字列に変換する。 例えば、

a = "01"
b = 2
d = a + b
e = a + b + c

のような例では、dおよびeの値は3になる。

こうした暗黙の変換は便利であると同時に、利用者の意図しない結果を生むこともある。

また、変数に入っているのがどちらかわからないが、必ず数値が必要という場合などにx + 0のように0を足したり、逆に必ず文字列が必要という場合などにx ""のように""を結合させたりする、という常套手段がある。

関数

[編集]

POSIXに準拠するAWKでは、関数を定義して使用することが可能である。

関数の定義は次のようになる。

function 関数名 (引数1, 引数2, ……)
{
   命令文1
   命令文2
   ……
}

AWKの変数は、引数を除いて全て大域変数であり、局所のスコープを持つのは引数として宣言された変数だけである。このため、技法として、関数定義で余分な引数を宣言し、それを局所変数として使う、ということが行なわれる。AWKでは、関数の呼び出し時に、実引数の個数が仮引数の個数より少なくても、省略とみなしエラーとしない。これを利用して、余分な引数を局所変数として使うのである。

function 関数名 (引数1, 引数2, 引数3, 局所変数1, 局所変数2, ……)
{
   ……
}

このように関数を定義した上で,呼び出すときに引数を3つしか使わなければ、局所変数1以降は局所変数として扱える。構文上の区別は無いが、判読性を向上させるために両者の間に十分な空白を挿入するのが慣例になっている。

function 関数名 (引数1, 引数2, 引数3,
局所変数1, 局所変数2, ……)
{
   ……
}

また、関数は再帰呼び出しもできる。

制御構造

[編集]

POSIX準拠のAWKの制御構造には以下のようなものがある。

if文
  • if () 式が真の時に実行される文
  • if () 式が真の時に実行される文 else 式が偽の時に実行される文
for/while文
  • for (初期化式; 条件式; 更新式) 実行される文
  • for (変数 in 配列) 実行される文
  • while () 実行される文
  • do 実行される文 while ()
  • break
  • continue
その他
next
以降の文の実行および以降のパターン処理をせずに、次のレコードの処理を開始する
nextfile
現在の入力ファイルの残りを読み込まずに、次のファイルの処理を開始する
return
関数の処理を停止し、関数の呼び出し元に制御を戻す。値が指定されてあれば値を返す。
exit
プログラムの実行を終了させる

また、制御構造の他に、以下の文がある。

  • {1; 2; ……; n}
  • print
  • printf
  • delete

連想配列の全部ないし一部の要素を削除

AWKの処理系

[編集]

もともとのAWKは、Research Unixに付属していたものであったが、 様々なプラットフォームに移植された他、GNU AWK(gawk)を代表に、他の実装も多い。

oawk (old awk)

[編集]
1977年から開発され、V7およびこれから派生したBSDなどのUNIXに付属したもの。『UNIXプログラミング環境』(en:The Unix Programming Environment)4.4節での説明で使われている版でもある[5]。ここではoawkと呼ぶ[注釈 4]
V7付属のawkと一般に利用されたoawkの違い
1979年のV7に含まれていたawkでは変数名に「_」が使えない、getline()関数が無い、文字列中で"\123"のような8進数エスケープ表記は使えない、などの制限があったが、1980年のV7addenda[注釈 5]でこれらが修正された。4BSDや、SystemIII, SystemVが含むoawkは、このV7addendaのoawkが基となっている。ただし、2.9BSDや3BSDではV7addendaの修正を含まず、V7付属のawkの制限が残っている。
V8以降のResearch Unixに付属したawk
V8(1985)以降のResearch Unixに付属していたawkは大幅な改修が加わったもので、後述のnawkに繋がるため、一般的にはoawkとは扱わない。
oawkの制限
後述のnawkと比較すると、oawkには以下のような制限あることが知られる。特に影響が大きいのはユーザ定義関数を作れないことである。
  • コマンドラインからAWK内部の変数の初期値を設定することができない。
  • ARGC, ARGVなどのコマンドライン引数を取得する定義済み変数が無い。
  • getline()関数は読み込むファイルを指定することができない。
  • split()関数はただ1種の文字で区切り[注釈 6]、文字列[注釈 7]や正規表現[注釈 8]などを使うことはできない。
  • 外部コマンドを呼び出すsystem()関数が無い。
  • sub(), gsub()などの文字列置換関数が無い。
  • sin(), cos(), atan2()などの数学関数が無い。
  • rand(), srand()などの乱数発生関数が無い。
  • ユーザ定義関数を作ることができない。
  • 多次元配列を使うことができない[注釈 9]
  • 冪乗演算子が無い[注釈 10]
  • ASCII制御文字のうち、"\a", "\b", "\f", "\r", "\v"などのエスケープ表記は未定義である[注釈 11]
BSD系Unixにおけるawk
2BSD, 3BSD, 4BSDはV7を元に発展したが、その過程でoawkを拡張することはなかった。そのため、4.2BSD, 4.3BSDをもとに商用化したSunOS (3まで)、Ultrix、SONY NEWS-OS (4まで)、NeXTSTEP (3.3まで)には既定ではoawkしか無い。
現在使用可能なoawk
現在もoawk由来の実装をインストールしているシステムとしてはSolarisが良く知られる。また、OpenSolarisによって公開されたツール群をを他のUNIXでもビルドできるように移植したものをProject Heirloomが配布しており、この中にもoawkに由来する実装が含まれる。ただしこの両者のoawkはあくまでもSolarisのoawkであるため、オリジナルのoawkの難点が一部修正されており[注釈 12]、Solarisの/bin/awkでの動作がV7での動作を保証するものではない。
発表当時のoawkを確認する最も確実な方法としては、SimHなどのシミュレートしたPDP-11VAXでV7や4BSDを動かすことである。V7をx86に移植したv7x86のawkにはバグがあり正しく動作しないので[注釈 13]、これによって動作を確認することは難しい。

nawk (new awk)

[編集]
awkの作者の一人であるカーニハンがoawkを改修したもので、SystemV Release 3(1988)[5]V10(1989)に付属していた[注釈 14]。oawkと区別するためにnawk(new awk)とも呼ばれる。新旧ではなく、同一作者のコードベースであることを強調する場合はoawkとnawkを合わせてone true awkなどとも呼ばれる。
oawkとnawkの非互換性
oawkとは式評価順序が変更されたため、単に予約語や関数が増えただけの上位互換にはなっていない。たとえばXPG3-XPG4 Base Migration Guide Version 2, 4.2 "Utility Migration Information" (p.51)では
while (n /= 10 > 1) ...
if (!"wk" ~ /bwk/) ...
の2つの例を非互換の例として挙げる。この2つはoawkでもnawkでも有効な式だが、oawkでは「n /= 10」「"wk" ~ /bwk/」が先に評価された後に「> 1」「!」が評価されるのに対し、nawkは「10 > 1」「!"wk"」が先に評価され、その後に「/=」「~ /bwk/」が評価される。結果として、nawkでは前者は無限ループを引き起こし[注釈 15]、後者は偽を返す[注釈 16]
ただし、このような違いは当時の規格類が要求するものではなく、あくまでも実装の違いであった。SystemV Release 3(1987)のソースにはoawkとnawkのソースが含められていたが、SystemV Release 3のインタフェースを定義するSVID Issue 2はoawkとnawkの2つを備えることを要求していたわけではない。実際、SVID Issue 2, Vol.2はawkコマンドのみを規定しており(pp.24-29)、そこではfunctionキーワードや、sub()などの文字列置換関数、冪乗演算子も無いため、oawkでもnawkでもSVID 2には準拠できる。SystemV由来のコードを含む多くの商用UNIXは2つのawkを含めていた。しかし、この2つをどのようにインストールするかはOSによって異なっており、たとえばSunOS 5.5.1ではoawkをawkコマンドとして、nawkはnawkコマンドとしてインストールする一方[注釈 17]、IRIX 6.5では逆にoawkをoawkコマンドとして、nawkをawkコマンドとしてインストールしていた。
商用UNIXにおけるnawkへの移行
SVID Issue 4(XPG4とPOSIXに準拠)ではawkコマンドとnawkコマンドの2つが記載されるようになったが、その扱いは異なっており、awkがLevel 1、nawkがLevel 2であった[注釈 18]。ここでのawkコマンドはユーザ定義関数のサポートを要求するものであり、oawkそのままではSVID 4に準拠できない[注釈 19]。また、SVID 4ではnawkコマンドは将来的に削除する予定であった(p.106)。これはnawkによってawkコマンドを一本化することを狙ったものであり、実際HP-UX(9以降)のようにoawkを完全に削除したものもあった。
386BSD派生OSにおけるnawkへの移行
バークレーの2BSD, 3BSD, 4BSD開発過程の中ではoawkの機能を拡張することはなかったため、4.3BSDからAT&Tのコードを除去するにあたってもoawkを書き直すのではなく後述のGNU awkで置き換える方針を取った[6]。このため、386BSDgithubで公開されている386BSD 2.0のソースにおけるawk”. 2024年9月22日閲覧。)、またこれから派生したNetBSD, FreeBSD, OpenBSDも当初はGNU awkのみを含んでいたが、OpenBSDは2.0(1996)からOpenBSD 2.0リリースノート”. 2024年9月22日閲覧。、FreeBSDは5.0(2003)FreeBSD 5.0リリースノート”. 2024年9月22日閲覧。から(ただしnawkは4.7 (2002)から既定でインストールしていた)、NetBSDでは2.0 (2004)から、既定のawkをnawkに切り替えている。Mac OS Xは当初からnawkであった。

gawk

[編集]
GNUプロジェクトによるAWKの実装。GNU/Linuxディストリビューションではawkという名前のプログラムがこの実装であることが多い。POSIX 1003.2コマンド言語とユーティリティ規約に定められた言語の定義に適合している。マルチバイト文字への対応やネットワークへの接続機能など、オリジナルのAWKには無い多数の拡張が加えられており、現在もバージョンアップが続いている。
jgawk
gawk がマルチバイト文字に対応する以前に作られた gawk の日本語文字対応拡張版。

mawk

[編集]
マイク・ブレナン(: Mike Brennan)作。旧版のawkに少数の拡張が加えられている。バイトコードに変換されて実行されるため,高速な動作が期待できる。またgawkよりもバイナリサイズが小さい。
mawk MBCS
木村浩一(ハンドル名:Bruce)によるmawkのマルチバイト拡張。
標準
AWKはawk(1)としてIEEE Std 1003.1-2017で標準化されている[7]。また、Linux Standard Baseでも指定コマンドになっている[8]

脚注

[編集]

注釈

[編集]
  1. ^ GNU awkのように拡張機能として持っている実装はあるが、POSIX標準などでは要求していない。
  2. ^ 著者らによる解説書では、第1章が改修前の機能に限定して書かれており、第2章以降が改修後の機能を用いている。
  3. ^ たとえば『プログラミング言語AWK』の日本語版の「訳書の序」に「Kernighan先生にお聞きしたところ、「AWK」は「ɔ́ːk」と発音し、A・W・Kとは決して言ってはならない、との事である。」とある。なお、訳者は同書の表紙に描かれている鳥はウミスズメAuk)としているが、これに関しては原書では特に言及は無い。
  4. ^ comp.lang.awkのFAQなどでもoawkと呼ぶ。
  5. ^ V7へのバグ修正やユーティリティの追加を行うための配布テープで、たとえばfsckはこれで追加された。全体の概要はThe Unix Heritage Societyが配布するソースのREADMEを参照。
  6. ^ 指定した区切り文字が連続している場合は1つの区切りとして扱う。nawk以降は、正規表現形式で1個の文字を指定した場合、連続した区切りパターンを1つの区切りとはせず、複数のものとして扱う。
  7. ^ oawkのsplit()で区切り文字に文字列を指定した場合、先頭の1文字だけが反映される。
  8. ^ oawkのsplit()で区切り文字に正規表現を指定した場合、シンタックスエラーを起こす。
  9. ^ ただし、awkの多次元配列は鍵データを連結させたものを鍵とする連想配列であるので、oawkでも同様の機能を実現することは可能である。
  10. ^ ただし、exp(), log()関数はoawkの段階から存在した。
  11. ^ "\t", "\n"のみ定義されていた。
  12. ^ たとえばprintf()の整数の丸めなど
  13. ^ UNIX V7を仮想マシン上で動かす手法のまとめ
  14. ^ V10のソースコードに含まれる変更メモによれば、前述のV8に付属していた「新しい版」よりもさらに機能が追加されている。
  15. ^ 10 > 1の結果が1にキャストされ、n /= 1を繰り返す
  16. ^ !"wk"が0として扱われ、さらに""として正規表現で比較される
  17. ^ SunOS 4.1.3では/bin/awkがoawk、/usr/bin/awkがnawkであった
  18. ^ SVID Issue 4以降、将来互換性がある変更しか加わらないものをLevel 1, 非互換変更の可能性や、削除の予定があるものをLevel 2としていた
  19. ^ ただし、コマンドラインオプションに関してはoawkのままで、nawkで追加された変数の初期値設定の"-v"オプションなどは要求されていない
引用エラー: <references> で定義されている name "FOOTNOTEアルフレッド・エイホブライアン・カーニハンペーター・ワインバーガ1989" の <ref> タグは、先行するテキスト内で使用されていません。

出典

[編集]
  1. ^ AWK(オーク)でプログラミング”. Googleブックス. 2024年7月17日閲覧。
  2. ^ awk 【Aho Kerninghan Weinberger】”. IT用語辞典. 2024年7月17日閲覧。
  3. ^ 【 awk 】コマンド(基本編)――テキストの加工とパターン処理を行う”. ITmedia. 2024年7月17日閲覧。
  4. ^ a b c アルフレッド・エイホ, ブライアン・カーニハン & ペーター・ワインバーガ 1989, pp. x-xi, §序文.
  5. ^ a b 志村拓, 鷲北賢 & 西村克信 1993, p. 43.
  6. ^ 4.4BSDにはgawk-2.15.2のソースが含まれている
  7. ^ awk”. IEEE 及び The Open Group (2013年). 2018年10月14日閲覧。
  8. ^ Relevant Commands”. Linux Foundation (2015年). 2018年10月14日閲覧。

参考文献

[編集]
  • プログラミング言語AWK
    1. Alfred V. Aho; Brian W. Kernighan; Peter J. Weinberger (1988). The AWK Programming Language. Addison-Wesley. ISBN 0-201-07981-X. https://archive.org/details/pdfy-MgN0H1joIoDVoIC7 2024年9月21日閲覧。  原書。
    2. アルフレッド・エイホブライアン・カーニハンペーター・ワインバーガ 著、足立高徳 訳『プログラミング言語AWKトッパン、1989年11月。ISBN 4-8101-8008-5  - 「AWK book」(AWK 本)などと呼ばれ、C言語におけるK&Rのような扱いの本である。日本版は版元の出版事業撤退により最初に絶版となる。
    3. A・エイホ、B・カーニハン、P・ワインバーガー 著、足立高徳 訳『プログラミング言語AWKシイエム・シイ出版部、2001年2月。ISBN 4901280406  - トッパン 1989年刊の再刊。
    4. A・エイホ、B・カーニハン、P・ワインバーガー 著、足立高徳 訳『プログラミング言語AWK新紀元社、2004年2月。ISBN 4-7753-0249-3  - 新紀元社から復刊されたものの、3度目の絶版となる。
    5. A・エイホ、B・カーニハン、P・ワインバーガー 著、足立高徳 訳『プログラミング言語AWKユニバーサル・シェル・プログラミング研究所、2010年1月。ISBN 978-4-904807-00-2  - ユニバーサル・シェル・プログラミング研究所から3度目の復刊がなされた。
  • 志村拓、鷲北賢、西村克信『AWKを256倍使うための本』アスキー、1993年3月。ISBN 4-7561-0162-3  - アスキーの256本のひとつで、通称「AWK256本」とも呼ばれており、現在も販売中のベストセラーである。
  • Dale Dougherty、アーノルド・ロビンス 著、福崎俊博 訳『sed & awk プログラミング 改訂版』オライリー・ジャパン、1997年10月。ISBN 4-900900-58-3 
  • Arnold Robbins 著、福崎俊博 訳『sed & awk デスクトップリファレンス』オライリー・ジャパン、2000年7月。ISBN 4-87311-017-3 

関連項目

[編集]

外部リンク

[編集]