a2p - Awk から Perl へのトランスレータ はコマンドラインで指定された (あるいは標準入力からの) awk スクリプトを とり、同等の働きをする スクリプトを標準出力に出力します。

オプション
オプションには以下のものがあります: デバッグフラグをセットします。 awk スクリプトが常にこの -F スイッチ付きで実行されることを指定します。 入力を分割して配列に格納する必要がない場合、 入力フィールドの名前を指定します。 例えば、パスワードファイルを処理する awk スクリプトを変換する場合、 このように指定します:

a2p -7 -nlogin.password.uid.gid.gcos.shell.home

フィールド名の区切りには任意のデリミタが使用できます。 a2p は、入力が常に指定した数のフィールドから成っていることを仮定します。

考察
a2p は人間と同じぐらいうまい変換はできませんが、 大抵の場合はそこそこうまく処理します。 場合によっては、 生成された perl スクリプトを吟味し、少し手を加えたいと思うことも あるでしょう。 以下にいくつかの場合を、順不同で説明します。 文字列を表す式のまわりに int() を付け、 数値として解釈されるようにする awk イディオムが あります (その引数は常に整数型なのですが)。 これは一般に perl では不要ですが、 a2p は引数が常に整数となるかどうか判断できないので、 このイディオムはそのまま残します。 ユーザはこれを取り除くことができます。 perl では数値比較と文字列比較は区別されています。 awk ではどちらにも同じ演算子が用いられ、 実行時にどちらの比較を行うかが決定されます。 この点で a2p は awk エミュレーションを完全には行おうとしません。 その代わり、a2p はどちらの種類の比較を行おうとしているのか推測します。 これはほとんどの場合正しいものですが、だまされることもあります。 推測を行った部分には "#???" というコメントが付与されますので、 それらの部分を調べ、中身をチェックすべきです。 ユーザは、少なくとも一度は -w スイッチ付きで perl を走らせるとよいでしょう。 こうすると、eq を使うべきところで == を使っている場合に警告を受けます。 存在しない配列要素でも、単にそれを参照しただけで存在するようになるか、 という点で、perl は awk の動作をエミュレートしようとしません。 何らかの理由で、このメカニズムに依存して後続の for...in のために ヌルエントリを作成しようとする場合、 perl ではヌルエントリは作成されません。 a2p が、(Fld1, Fld2, Fld3...) のような、変数のリストへの代入を行う行を 分割する場合、 上に述べた -n オプションを用いて再度 a2p を走らせた方がいいかもしれません。 これにより、スクリプト内のフィールドに名前を付けます。 そうではなく、分割して配列に格納する場合、 その分割はおそらくどこかでフィールド数を参照しているでしょう。 awk の exit ステートメントは必ずしも exit せず、 END ブロックがあればそこへ処理が移ります。 ある条件下で END ブロックをバイパスするような細工を END ブロックに 仕掛けてある awk スクリプトは、 END ブロック内の条件文を取り除き、perl スクリプトから直接 exit するように 修正することで簡単化できます。 perl には 2 種類の配列、すなわち数値でインデックスされる配列と連想配列とが あります。 通常、awk の配列は連想配列に変換されますが、 もしそのインデックスが常に数値であるとわかったら、 配列添字の {...} を [...] に変更できます。 連想配列に対する繰り返し処理は関数 keys() を用いて行われますが、 数値配列に対してはそうではありません。 問題となっている配列の繰り返し操作を行うあらゆるループ構造を 修正する必要があるかもしれません。 awk は起動時、OFMT の値が %.6g であると仮定しています。 perl でこれに相当する変数 $# は、初期値として %.20g を持っています。 OFMT のデフォルト値を用いる場合は $# を明示的に設定して下さい。 awk スクリプトでは、行の先頭付近で行分割 (split) 操作が暗黙的に 繰り返されます。 場合によっては、全体レコードをテストする何らかの条件文より下に これを移動させることができます。 そうすることで無用な行分割処理を避けることができます。 美的理由から配列の基底 $[ を元々の 1 から perl でのデフォルトである 0 に 変更したいこともあるでしょう。 しかし、全ての配列添字式だけでなく、全ての substr() および index() 関数も 適合するように修正しなければならないことを忘れないで下さい。 "# awk は馬鹿だからこうやって工夫しています" といった気の利いたコメントは、 そのまま修正されずに渡されます。 awk スクリプトはしばしばシェルスクリプトに埋め込まれ、 awk の入出力がパイプで接続されます。 こういったシェルスクリプトのラッパも perl スクリプトに取り込める場合が かなりあります。 perl なら入出力パイプを開始でき、 awk が自分ではできなかった他の処理も行うことができるからです。 特殊変数 RSTART および RLENGTH を参照するスクリプトは、 これらの変数を定義するパターン照合のスコープの中で参照されている限り、 変数 $`, $&, $' を参照することで簡単化できる場合がかなりあります。 生成された perl スクリプトには、 getline および print に関する awk の意味規則に対処するための サブルーチンが定義されている場合があります。 a2p は通常、効率よりも正確さを選ぶからです。 ほとんどの場合、ご丁寧に意味規則に対処してくれるサブルーチンを捨てて、 もっと効率的なコードに書き換えることができます。 効率を上げるために、 サブルーチンで最後に実行される return ステートメントから キーワード return を取り除くことができる場合があります。 a2p は最も一般的な場合は見つけますが、 稀にある埋め込まれたブロックを解析したりしません。 ARGV[0] は $ARGV0 に変換されますが、ARGV[n] は $ARGV[$n] に変換されます。 ARGV[0] を含めて繰り返し処理を行おうとするループは、 うまくいきません。 a2p は環境変数を参照しません。 Larry Wall <lwall@jpl-devvax.Jpl.Nasa.Gov> perl perl コンパイラ/インタプリタ
s2p sed から perl へのトランスレータ 実行時にオペランドを調べることで、文字列演算か数値演算かの選択で awk の エミュレーションを行うことは可能でしょうが、 プログラムは肥大し、非効率的になるでしょう。 なお、a2p の推測はほとんど常に正しく行われます。 awk 文法ツリー用の領域は現在のところ静的に確保しており、 不足する可能性があります。