S-JIS[2007-03-06/2014-05-01] 変更履歴

awk(オーク) 〔オプション〕 ファイル名…

C言語に似た文法を持つスクリプト言語。テキストファイルを加工するのに使う。


実行方法

% awk "1行プログラム" hoge.txt
% awk -f プログラムファイル hoge.txt

入力ファイルを読み込み、データを1行ずつ、プログラムに従って編集・出力する。(標準出力に出力される)
入力ファイルを省略した場合は、標準入力からデータを読み込む。

-fオプションでファイル名に「-(ハイフン)」を指定すると、標準入力からプログラムが入力できる。[2007-04-24]
ただし「シェルの中にヒアドキュメントでプログラムを書く」という使い方をする場合は $シェルの変数と認識されてしまうので、\でエスケープする必要がある。

% cat sample.sh
#!/bin/sh
awk -f - hoge.txt <<EOF
{ print \$0 }
EOF

プログラムファイルに実行権限を付けて ファイルの先頭行に「#!/bin/awk -f(awkのコマンドのパスと-fオプション)を入れると、ファイルを直接実行することが出来る。[2007-05-12]

% cat exe.awk
#!/bin/awk -f
BEGIN { print "zzz" }
{ print FILENAME;exit }
% chmod +x exe.awk
% exe.awk input.txt
zzz
input.txt

文法

プログラムは、おおよそ1行に『条件』と『その条件が満たされたときの処理』を記述していく。
条件・処理は、入力データの1行ずつに適用される。
複数行のプログラムを書いた場合は、入力データの1行ずつに対し、順番に条件がチェックされる。(途中でnext命令を実行すると、次のデータ行に移る)

入力データの行がA,B,Cとあり、プログラムの行がp1,p2だった場合、「Aに対してp1→p2」⇒「Bに対してp1→p2」⇒「Cに対してp1→p2」という順で処理される。

プログラム行の形式 動作 備考
条件 { 処理 } 条件が満たされた時に処理を行う。  
条件 条件が満たされた時に、入力データ行をそのまま出力する。 { print }という処理が省略されている。
{ 処理 } 常に処理を行う。 条件が省略されている。
#〜 行コメント  

条件(パターン)

条件には、C言語で使えるような比較演算が使用できる。&&や||も使える。
その条件が満たされたとき、直後に書かれているブロック(処理)が実行される。
条件を省略すると、常に処理が実行される。

基本的には、「“$0$1といった変数”に格納されている文字列」と比較することがほとんど。
awkでは、文字列に対しても「==」といった比較演算子がそのままの意味で使える。

また、正規表現を使うことも出来る。[2007-05-12]

/正規表現/ $0の中に正規表現にマッチする箇所があれば、真 if文では使えない
!/正規表現/ $0の中に正規表現にマッチする箇所が無ければ、真
変数 ~ /正規表現/ 変数の中に正規表現にマッチする箇所があれば、真 if文でも使える
変数 !~ /正規表現/ 変数の中に正規表現にマッチする箇所が無ければ、真


行の範囲指定をすることも出来る。[2007-05-14]

開始条件,終了条件 開始条件に合致した行から、終了条件に合致する行まで、全ての行を出力する。
終了条件が出た後に再び開始条件に合致したら、再度出力対象になる。
行番号での範囲指定


その他に、特殊な条件が存在する。(必要ないなら省略可)

BEGIN ファイル処理の一番最初に一回だけ呼ばれる。変数の初期化に使える。
END ファイル処理の一番最後に一回だけ呼ばれる。

※複数のデータファイルが指定されている場合でも、BEGIN・ENDは 全体の最初と最後の一回ずつしか呼ばれない。[2007-05-14]

条件を複数行にわたって書きたい場合は、行末に「\」を付けることで 次の行に継続できる。[2007-05-14]

入力データの行がA,B,Cで、プログラムがBEGIN,p,ENDだった場合、「BEGIN」⇒「Aに対してp」⇒「Bに対してp」⇒「Cに対してp」⇒「END」という順で処理される。

特定位置の文字列の件数をカウントする例:

BEGIN { count = 0; }
$1 == "hoge" { count++; }
END   { print count; }

文字列のある行数をカウントする例:

BEGIN { cnt1=0;cnt2=0; }
/hoge1/ { cnt1++; }
/hoge2/ { cnt2++; }
END   { print cnt1,cnt2; }

処理(アクション)

「{ 〜 }」ブロックでくくると、データを処理する動作(アクション・命令)の記述となる。
複数の命令を記述する場合は、セミコロン「;」で区切る。(C言語と異なり、末尾のセミコロンは不要だが、付けても構わない)
ブロックの中は改行可能。

変数も使用できる。変数の定義(宣言)は特に必要なく、代入すればそのまま使える。
変数には型(数値・文字列)といった概念は無く、数値も文字列もどちらも入れられる。
計算に使えば数値として扱われるので、数値として代入したいときは「a = $2 * 1」のように演算を行ってやる。

主なアクション
命令 内容
print 入力行全体をそのまま出力する。「print $0」と同等。
print 値,値… 変数の値や文字列を出力する。カンマで値を並べると、OFSの文字で区切られて出力される。
printf "書式",値… C言語のprintfと同様の書式で出力する。
C言語と異なり、%dや%sといった書式指定に応じて 値が数値や文字列として扱われる。
if (〜) { 〜 } C言語のif文と同様。
next 次の入力データ行に移る。
(現在の入力行に対する残りのプログラムはスキップされ、次のデータ行が先頭のプログラムから適用される)
exit 入力ファイルの処理を終了する。「値」は、awkのリターンコードとなる。

カンマ区切りファイルの特定のデータを書き換える例:

BEGIN { FS = ","; OFS = ","; ret_code=0; }
$2 == "localhost" { print $1,"127.0.0.1"; ret_code++; next; }
{ print }
END { exit ret_code; }

$変数

$0は入力データの1行全体の文字列で、$1,$2…は入力行をスペース(FS参照)で区切った単語(文字列)を表している。

$1や$2に値を代入すると、$0も置き換わる。その際には、OFSで区切った形式となる。
元の文字列が複数のスペースで区切られていたとしても、OFS1文字分になる。

「$」の直後には、数値だけでなく 変数や式も使用可能。$nとか$(n-1)とか。


組み込み変数

デフォルトで、以下のような変数が定義されている。

変数名 内容 デフォルト値
FILENAME 入力ファイル名 標準入力からの場合は、「-」
FS フィールドセパレーター。入力時の$1$2の区切り 空白とタブ
OFS 出力フィールドセパレーター 空白
NF 現在のレコード(入力行)のフィールド数  
NR 現在のレコード(入力行)の行番号  
RS レコードセパレーター 改行
ORS 出力レコードセパレーター 改行

複数行にわたるデータを1行にまとめてカンマ区切りで出力する例。[2014-05-01]
ORS(出力レコードセパレーター)を空文字列にすると、printで出力したときに改行されなくなる。

$ awk 'BEGIN { ORS=""; SEP="" } { print SEP$0; SEP="," }' input.txt

組み込み関数

デフォルトで、以下のような関数が使える。

関数名 内容
substr(文字列,位置,長さ) 部分文字列の取得。位置は1から。
index(文字列,探索文字列) 文字列の中にある、探索文字列の位置を返す。[2014-05-01]
先頭にあれば1が返る。見つからなければ0が返る。
length(文字列) 文字列の長さの取得。
文字列 文字列 スペース区切りで文字列(変数)を並べると、文字列を結合する。(いわゆるconcat)
int(数値) 小数点以下切り捨て。

関数定義

関数はfunctionで定義できる。[2011-12-26]
条件(パターン)の並びと同列の位置に書く。

function 関数名(変数名, …) {
	〜処理〜
}
#呼び出す例
{ 関数名(値, …); }

UNIXコマンドへ戻る / 技術メモへ戻る
メールの送信先:ひしだま