メモ:awkで改行+複数行追記

先日のsedで改行する件の続きです。

日記にブックマークコメントを頂きました。ありがとうございます。

awk '/#hoge=0/,/^#/{print $0"\nhoge=1\nmoga=2";getline}1' じゃ変だしなぁ。

はてなブックマーク - Roccoのブックマーク / 2010年9月23日

この方法でも、欲しい結果が返ってきました! ヤッター。

しかし、恥ずかしながらawkを知らないので、ヘンかどうかを判断できない上に、何をやっているのかもよく分かりません。残念すぎる。というわけで、上の1行が何をしているかをawkの勉強がてら調べました。Hello awkです。

範囲パターン

/最初のパターン/,/最後のパターン/

最初のパターンに一致すると、範囲パターンが真になったとみなされる、最後のパターンに一致すると、後続の行では範囲パターンが偽になったとみなされる。

上のスクリプトだと、「#hoge=0」に一致する行があれば、「#」が先頭にある行までの間、後続のアクションを実行する。

getline

わからない。すみませんすみません…。なぜここにgetlineが必要なのかわからない。

getline、特に、引数なしgetlineについて調べた限りでは、$0をセット(再構成?)しようとしているのかなと思うのですが、「;getline」を抜いて実行しても出力結果は同じなのです。# Ubuntu 上の gawk を使用

アクションの直後にある「1」

これもわからない。アクションの外にある数字の意味が、色々調べたもののわかりません。HANDY ONE-LINE SCRIPTS FOR AWKという文書に次の記述があり、近いかと思ったのですが。

 awk '1;{print ""}'
 awk 'BEGIN{ORS="\n\n"};1'

・・・遠いかもしれない。まだ謎のままデス。とりあえず、実行してミマシタ。

(1を含む)0以外の数字にしたときの出力がコレ。

#hogeりたければ値を設定。
#hoge=0
hoge=1
moga=2
#
#

0にしたとき、また、何も数字をつけないときの出力がコレ。

#hoge=0
hoge=1
moga=2

何も指定しないと、開始パターンを含む行から終了パターンを含まない行までのみを表示する・・・のかな?

参考資料

言語仕様はまだよくわかりませんが、「人が書いたシェルにawkが出てくると、つい目が滑ってスルーしてしまう奇病」は治りそうです。良い機会をありがとうございます。

余談:awkでびっくりしたこと

ローカル変数の定義方法。

awkでは、すべての変数がグローバル変数として扱われるため、呼出し時に引数の数が正しいかどうかチェックしないことを利用して、仮引数と一緒の()の中にローカル変数を書くらしい。

awkに関することで、今のところコレに一番びっくりしました。