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
は処理するファイル名