awkの基本形

5月 31, 2010

シェルに組み込むこともよくあるであろうスクリプト言語、awkについてあらためて
基本をまとめてみる。

awkの動作は次のようになっている。

1.オプションを解析し、初期設定を行う。
2.スクリプトの構文チェックを行い、エラーがあればエラーメッセージを出力して終了。
エラーがなければ次へ進む。
3.BIGINブロックがあればBIGINブロックの処理を行う。なければ次へ。
4.データを一行ずつ読み込み、対象データ(メインブロックに書かれた命令を読み込むデータ)
がなくなるまで1行ずつ実行する。
5.ENDブロックがあればENDブロックの処理を行う。


以下基本パターン。標準入力から入力された行がパターンに一致した場合、
その行に対してコマンドを実行する。一致しなければ何もしない。

awk ‘
/pattern/ {command}


パターンを省略した場合はどの入力行に対しても実行される。
以下、代表的なパターン。
awk -基本動作

BIGINはスクリプトを初期化する働きがある。BIGINに伴うアクションは入力行が読み込まれる
前に処理されるため、タイトルや処理内容を表示させたり、各種変数を初期化する際に利用する。

以下はsample.txtのレコード区切りをタブに変更して全フィールドを出力。

$ awk ‘BEGIN {RS = “¥t”} {print $0} sample.txt


ENDに伴うアクションはawkが処理を終えた後に一度だけ実行される。
最終結果の出力や後処理を行うときに利用される。

以下はsample.txt全体のフィールド数を出力。

$ awk ‘{num+= NF} END {print num}’


//で囲むパターンには単純な文字列や数値の他、拡張正規表現を指定できる。
以下は単純にsample.txtからerrorを含む行の数を出力する。

$ awk ‘/error/{num++} END {print num}’ sample.txt


しかし、これだけなら$ grep error sample.txt | wc -l でもいい。
もっと複雑なことをやりたいときにawkを使うべきなのだろう。

以下、awkで定義されている変数。
awk2

オプションにより初期設定を変更したり、スクリプトファイルを利用できる。
awk-option

awkのレコードとフィールドについて。
awkは標準入力や指定したファイルから1行分のデータを読み込むが、この1行分のデータを
レコードと呼ぶ。awkはレコード単位でデータを読み込み、フィールドと呼ばれる単位に
分割する。デフォルトではレコードの区切りは改行コード、フィールド区切りは1つ以上の空白となる。
これらはそれぞれ
RS(Record Separator)およびFS(Field Separator)で定義されている。

上の表にもあるように、フィールド区切りを変更したい場合は-Fオプションを利用する。
以下はsample.txtからフィールド区切りに「:」(コロン)を指定し、第1フィールドを出力。

$ cat sample.txt | awk -F: ‘{print $1}’


フィールド区切りに複数の文字を指定することも可能。
以下はコロンとピリオドの2つを指定し、タブ区切りで第3フィールドまで出力。

$ cat sample.txt | awk -F’[:.]‘ ‘{print $1 “¥t” $2 “¥t” $3}’


特定の行を取り出したい時。行はNRで定義する。
2行目のみ取得するには以下のように。

$ cat sample.txt | awk ‘(NR == 2)’


2行目の第5フィールドを取得。

$ cat sample.txt | awk ‘(NR == 2){print $5}’


デリミタ指定を入れる場合。

$ cat sample.txt | awk -F: ‘(NR == 2){print $5}’


ところでawkはターミナルで直接実行すればOKでも、ssh経由のコマンドやCronでは
動作しないことがある。スクリプトには {print $1} と書いているのにCronエラーで
{print /dev/null} と出力されたり。。なんなんだろう、あれ。
調べるのも面倒なので代替手段(cutコマンド)を使ってしまっているが、、、

主な出典
シェル&Perl入門(サイエンス社)



Categories: shell