#################################################################### # awk に関するメモ #################################################################### ======================================================================= 基本的な例 ======================================================================= ■基本形 awk 'プログラム' 入力ファイル awk -f プログラムファイル名 入力ファイル プログラムの書き方は以下のようになる パターン {アクション} # パターンは勿論 RE である パターン {アクション} ... or パターン {アクション; アクション}[;] パターン{アクション; アクション} パターンにマッチすると,アクションが実行される 文は ; 改行 } のどれかで終了する 入力ファイルの内容は変更しない 入力ファイルを指定しなければ,標準入力が入力して利用される 出力は標準出力へ ■ egrep のエミュレート awk '/RE/{print}' filenames awk '/RE/' filenames # アクションを省略すると print が使われる ■ cat のエミュレート awk '{print}' filenames # パターンを省略するとすべてにマッチ ■フィールド 入力行は自動的に複数のフィールドに分割される 各フィールドは $1, $2, ... $NF となる $0 = 入力行全体 NF = フィールド総数を表す変数 (sed の変数にはフィールド以外 $ はつけない) ex) who | awk '{print $1,$5}' #ユーザのログイン時刻を表示 who | awk '{print $1"\t"$5}' #タブを含んで見やすくした who | awk '{print $1"\t"$5}' | sort +1 -n # 時刻順にソート who | awk '{print $1"\t"substr($5,1,2)}' #ログイン時刻の分の部分を削除 ■フィールドセパレータ -F オプションまたは FS 変数への代入で変更可能 デフォルトはタブと空白文字 ex) awk -F: '{print $1, $4}' /etc/passwd # ログイン名と本名を表示 ■表示 awk '{print $1 $3} foo # 続けて表示 awk '{print $1, $3} foo # 出力フィールドセパレータで区切って表示 awk '{printf "%4d %s\n", $1 $3} foo #フォーマットして表示 ■パターン awk '$2==""' foo # $2 が空文字列 awk '$2 ~ /^$/' foo # 同上(正規表現のマッチを利用) awk '$2 !~ /./' foo # 同上(正規表現の非マッチを利用) awk 'length($2) == 0' foo # 同上(関数を利用) awk 'NF % 2 !=0' foo # フィールド数が奇数 awk 'length($0) > 72' foo # 一行が長すぎる awk 'BEGIN{FS=":"} $1=="susumu"' /etc/passwd # BEGIN パターンの利用(FS の変更) awk 'END{print NR}' foo # END パターンの利用(行数の表示) ■算術演算と変数 awk '{s+=$1} END{print s}' foo # foo の第一フィールドの値の和を表示 awk '{nc+=length($0)+1; nw+=NF} END {print NR,nw,nc}' foo # wc のエミュレート 変数は暗黙の内に初期化されている 変数に文字列・数値の区別はない ■文字列定数 "" ダブルクォートで囲む(C と同じ) ■配列 連想配列と普通の配列が一緒になっている a["hogehoeg"] a[1] ともに OK であり,名前空間は同一である ■演算子(優先度の高い順) ++ -- * / % + - (何も無し) 文字列の連結 > >= < <= == != ~ !~ 関係演算子 (~ は正規表現のマッチ) ! 論理否定 && 論理積 || 論理和 = += -= /= %= 代入 ■組み込み変数 FILENAME 現入力ファイル名 NF 現レコード中のフィールド数 NR 現レコード番号(つまり行番号) FS 入力フィールドセパレータ(デフォルトはスペースとタブ) OFS 出力レコードセパレータ(デフォルトはスペース) RS 入力レコードセパレータ(デフォルトは改行文字) ORS 出力レコードセパレータ(デフォルトは改行文字) OFMT 数値の出力形式(デフォルトは %.6g) ■制御構造 C と同じ(for で foreach のようなことができる以外) print, printf ではリダイレクト,パイプが使用できる 文は以下のいずれか if (expression) statement [else statement] while (expression) satement do satement while (expression) for (expression; expression; expression) statement for (var in array) statement # foreach のような用法 # var には array の添字の変数が予想できない順番で入る # (ハッシュのキーが順番に得られると考えた方が良いだろう) # ソートするには /usr/bin/sort の手助けが必要だ break continue {[statement] ...} # 複文 expression print [expression-list] [>expression] # リダイレクト print [expression-list] [|cmd] # パイプ printf format [, expression-list] [>expression] printf format [, expression-list] [|cmd] exit [expr] # expr は終了ステータス ■組み込み関数 ■算術関数 cos(x), sin(x), exp(x), log(x), sqrt(x), int(x) ■文字列関数 index(s, t) 文字列 s 中で文字列 t が最初に出現する位置を返 す(先頭が 1,出現しなければ 0) int(s) 整数値になるよう s を切り捨てる length(s) 文字列の長さ match(s, re) 文字列 s 中で正規表現 re に最初にマッチする位置 split(s, a, fs) 文字列 s を正規表現 fs でフィールド分けし,配列 a の各要素(a[1], a[2],...a[n])に代入する 値 n (要素数)を返す (nawk では fs は正規表現のようだが,awk では田 だの文字列のような感じが...) sprintf(fmt, expr, expr) 同型式の printf で出力される文字列を返す substr(s, m, n) 文字列 s 中の m 番目から始まる長さ n の部分文字 列を返す ■入出力関数 getline $0 に現入力ファイルの次のレコードを設定する 正常時 1, EOF で 0, エラーで -1 を返す ======================================================================= その他 ======================================================================= ■ nawk と gawk 標準の awk は貧弱な機能しか持っていない。nawk, gawk はより強力な関 数,組み込み変数,システムとの連係がサポートされている ■ perl で awk を真似る awk '/^#/' foo # # で始まる行を表示 perl -n -e "print if /^#/;" foo