Carpe Diem

備忘録

AWKの基本的な使い方

概要

AWKは文字列の検索、抽出、変換などができるプログラミング言語です。
UnixLinuxは基本的にテキストをプロトコルとしています。AWKを扱えるとそのプロトコルをより柔軟に扱えることになります。

前提知識

あらかじめ知っておくべき知識を書いていきます。

パターンとアクション

awkの書式は以下のようになっています。

$ awk 'パターン {アクション}'

パターンとアクションは両方同時に書く必要はなく、以下のようになります。

ケース どうなるか
アクションのみ 全てのレコードに対してアクションが実行される
パターンのみ パターンにマッチしたレコードを表示する
パターンもアクションもない 何も表示されない

アクションのみの場合はこんな感じに書きますし、

$ echo "a b c" | awk '{print $0}'
a b c

パターンのみの場合はこんなふうに書きます。

$ seq 1 10 | awk '$0 % 2 == 0'
2
4
6
8
10

AWKの要素は1から数える

大抵のプログラミング言語ではarrayなど要素は0から始まりますが、awkは1から始まります。

$ echo "a b c d" | awk '{print $1}'
a

$0はレコード全体を表示します。

$ echo "a b c d" | awk '{print $0}'
a b c d

AWKの真偽値

真偽値のルールは以下です。

  • 数字の0
  • 空文字列は
  • それ以外は
# 数字の0
$ echo "foo" | awk '0'
# 0じゃない数字
$ echo "foo" | awk '2'
foo
# 空文字列
$ echo "foo" | awk '""'
# 空じゃない文字列
$ echo "foo" | awk '"bar"'
foo

代入の戻り値は左辺値

代入のケースは少し特殊です。AWKは破壊的な代入が可能ですが、戻り値は左辺の値になります。

# 左辺値はBなので真
$ echo "a b c" | awk '$2 = "B"'
a B c
# 左辺値が空文字だから偽
$ echo "a b c" | awk '$2 = ""'

組込変数

AWKにはあらかじめいくつかの組込変数が用意されています。

組込変数 説明 デフォルト値
RS Record Separator
入力のレコード区切り文字
改行
FS Field Separator
入力のフィールド区切り文字
連続するスペースorタブ文字
ORS Output Record Separator
出力のレコード区切り文字
改行
OFS Output Field Separator
出力のフィールド区切り文字
スペース1つ
NR Number of Record
現在のレコード数
NF Number of Field
現在のレコードのフィールド数

基本的な使い方

検索

/で囲んだ正規表現で記述できます。

$ echo "foo bar baz" | awk '/foo/'
foo bar baz

ちなみにこれは実は$0 ~を省略したシンタックスシュガーです。なので

$ echo "foo bar baz" | awk '$0 ~ /foo/'
foo bar baz

これと同じです。

文字列の抜き出し

substr()を使います。

# 開始文字のみ指定
$ echo "abcde" | awk '{print substr($0, 2)}'
bcde
# 開始文字〜何文字まで抜き出すか指定
$ echo "abcde" | awk '{print substr($0, 2, 3)}'
bcd

連接

AWKで文字列を繋げる(連接する)場合は文字列の間にスペースを置きます。

$ echo "abc" | awk '{print $0 "def" "ghi"}'
abcdefghi

sprintf()でフォーマット指定もできます。

$ echo "abc" | awk '{print sprintf("%s%s%d", $0, "def", 5)}'
abcdef5

置換

最初にマッチした文字列だけ置換するsub()や、マッチした全ての文字列を置換するgsub()があります。

# sub()
$ echo 'abcde' | awk '{sub(/./, "A"); print $0}'
Abcde
# gsub()
$ echo 'abcde' | awk '{gsub(/./, "A"); print $0}'
AAAAA

インプットのField Separatorを変更する

-Fを使います。例えばCSVファイルを扱いたい場合は

$ echo 'a,b,c' | awk -F "," '{print $2}'
b

のようにします。

※他の変数は-vオプションで指定するのに対し、変数FSだけはこのように-Fオプションで直接指定できます。

アウトプットのField Separatorを変更する

OFSを使います。ただこれだけではうまくいきません。

$ echo 'a b c' | awk -v OFS=',' '{print $0}'
a b c

これは"a b c"を読み込んだ際にAWKがフィールド分割を行なっているだけで、新しくフィールドの再構築を行なっていないためです。フィールドの再構築をするには$1 = $1という特殊な書き方をします。

$ echo 'a b c' | awk -v OFS=',' '{$1 = $1; print $0}'
a,b,c

参考書籍

「シェル芸」に効く!AWK処方箋

「シェル芸」に効く!AWK処方箋