awk
概要
- プログラミング言語の1つ
- 特定の文字で区切られたデータが記述されたテキストを処理する際に便利
- 現在の Linux ディストリビューションで使える awk の実体は awk ではなく、gawk (awk は gawk のリンクになっている)
処理の流れ
- 1行ずつ処理していく
- 以下の順にプログラムは進む- 前処理: BEGIN{…}- 省略可
 
- 本処理: {…}- {…} の前にパターン (正規表現可) をつけると、パターンの行のみ処理する
 
- 後処理: END{…}- 省略可
 
 
- awk にはファイル保存機能はないため、リダイレクトやパイプを使ってデータを保存したり、渡したりする
実行方法
- ワンライナー
 $ awk [オプション] '処理内容' データ 
- バッチファイル1 (awk に読み込ませる)
 $ awk [オプション] -f バッチファイル データ - バッチファイルとは awk の処理内容を記述したファイル
 
- バッチファイル2 (単体で動かす)
 $ chmod +x バッチファイル $ ./バッチファイル データ - ただし、バッチファイルの先頭に#!/usr/bin/awk -fを付けること (/usr/bin/awk は環境によって異なるので、which コマンドなどで確認すること)
 
- パイプデータ処理
 $ コマンド | awk [オプション] 
オプション
| 表記 | 効果 | 備考 | 
|---|---|---|
| -F 区切り文字 | 区切り文字(入力フィールドセパレータ)の変更 | |
| -v 変数名=変数値 | awk 内に変数を渡す | シェル内での実行の際、シェル変数を awk に渡したい時に使う | 
| -f バッチファイル | バッチファイルに記述した処理をする | |
用語
- レコード: 入力レコードセパレータで分割されたデータ
- フィールド: フィールドセパレータで分割されたデータ
構文
全体のコード
#!/usr/bin/awk
BEGIN{
	開始処理
}
/正規表現パターン1/{
	パターン1に対する処理
}
/正規表現パターン2/{
	パターン2に対する処理
}
:
END{
	終了処理
}
変数
- 変数- $0: レコード (行全体)
- $1, $2, $3, …: フィールドの各データ
- 変数は自分で定義することも可能 (定義は不要)
 
- よく使う組み込み変数- FS: 区切り文字 (データ間を区切る文字)- オプション-F 区切り文字で変更可 (区切り文字は正規表現での表現可)
 
 
配列
- 複数のデータをひとまとめにした変数
- 定義は不要
- 配列のインデックスは 1 から始まる (0 ではない)
演算子
- 演算- 四則演算が使える- +, -, *, /
 
- インクリメンタル (++) やデクリメント (–) が使える
- 代入演算子 (+= や -= など) が使える
 
if
- 条件を分岐する場合
 if (条件1){ 処理1 else if (条件2){ 処理2 } else{ 処理3 }
- 例:
 if (i == 0){ print "0" } else if (0 < i && i < 10){ print "1-9" } else{ print "10 over" }
- 条件式で使える記号- <, >, ⇐, ⇒, == (数値、文字列の比較に使う), !=
- &&, ||
- 正規表現では ~ で正規表現とつなげる (例: i ~ /hoge/)
 
for
- 繰り返し処理をする場合に使う
 for (変数の初期化; 変数の条件式; 変数の変化){ 処理 }- C 言語の for 文と一緒
 
- 例
 for (i = 0; i < 3; i ++){ print "Hello" }Hello を 3 回出力 
よく使う関数
- print
 print "文字列" - 変数の中身などを出力
- 複数のデータを表示する場合は、スペースで区切って列挙 (例: print $1 "\t" $2 $3)
- スペースやタブを出力したい場合は、“ ”や“\t”を変数の間に入れる
 
- printf
 printf("フォーマット", 値)- C 言語の printf と同じく、変数の内容を整形して表示
- %s: 文字列 (s の前に整数があると、スペースでその数だけの幅に整形する; 正の整数を入れると右揃え、負の整数を入れると左揃え)
- %d: 整数 (d の前に整数があると、スペースでその数だけの幅に整形する; 正の整数を入れると右揃え、負の整数を入れると左揃え)
- %f: 浮動小数 (f の前に小数があると、整数部を全体の幅、小数部を小数点以下の桁数にする; 整数部の前に 0 を付けると、ゼロで空白部を埋める)
 
- sub, gsub
 sub(正規表現, 置換後の文字列, 対象とする文字列) - 文字列の置換をする
- sub は 1 回のみ、gsub は繰り返し置換 (正規表現の s/str/replace/g) みたいなもの- 例: str = 'banana' として、a を “” (削除) する場合- sub
 sub(/a/, "", str) ⇒ bnana 
- gsub
 gsub(/a/, "", str) ⇒ bnn 
 
 
 
- split
 split(対象文字列, 配列, 区切り文字) - 対象文字列 を 区切り文字 で区切って、配列 に代入する関数
- 返り値は、配列の要素数になる
 hoge = split("banana", data, "a")hoge は 3、data には「b」「n」「n」が入る 
 
- length
 length(配列) - 文字列や配列の長さを出力
 
その他
- 改行- 複数行を1行にしたい(ワンライナー)場合、「;」が改行の代わりになる
 
awk プログラムの例
合計と平均算出
- 対象データ: 第1フィールドにステップ数、第2フィールドに値があるデータ
- コード (バッチファイル)
 - sumaverage.awk
- #!/usr/bin/awk -f BEGIN{ total = 0 count = 0 } $0 !~ /^#/{ total += $2 count ++ } END{ average = total / count print "Total: " total print "Average: " average } 
 
- 実行方法- バッチファイル
 $ awk -f sumaverage.awk data.txt 
- バッチファイル単体
 $ chmod +x sumaverage.awk $ ./sumaverage.awk data.txt 
- コード (ワンライナー)
 $ awk 'BEGIN{total = 0; count = 0} $0!~/^#/{total += $2; count ++} END{average = total / count; print "Total: " total; print "Average: " average}' 
 
Tips
シェル変数をパターンとして引き渡す
- -vオプションで変数を渡しつつ、- $0 ~ VARでマッチさせる
 - $ awk -v VAR '$0 ~ VAR{print $0}' FILE - VARは変数名
- FILEは処理するファイル名