awk はテキストファイルや標準入力を行単位で処理するプログラミング言語/コマンドです。
CSV のフィールド抽出、集計、フォーマット変換など、シェルスクリプトの中で非常によく使われます。
awk の基本構文
awk 'パターン { アクション }' ファイル名
- パターン: 行を処理する条件(省略すると全行が対象)
- アクション: 条件に一致した行に対して実行する処理
# 全行を表示(cat と同じ)
awk '{ print }' /etc/passwd
フィールドの参照
awk はデフォルトで空白(スペース・タブ)を区切り文字として各行を分割します。
分割された各フィールドは $1、$2、$3 … で参照でき、$0 は行全体を指します。
# /etc/passwd の1列目(ユーザー名)を表示
awk -F: '{ print $1 }' /etc/passwd
-F: オプションで区切り文字をコロン : に変更しています。
# スペース区切りのログから3番目のフィールドを表示
awk '{ print $3 }' access.log
特定のパターンにマッチする行を処理する
# "error" を含む行だけ表示
awk '/error/ { print }' app.log
# 3列目が 200 の行だけ表示
awk '$3 == 200 { print }' access.log
# 3列目が 500 以上の行を表示
awk '$3 >= 500 { print }' access.log
複数フィールドを組み合わせて出力する
# /etc/passwd からユーザー名とホームディレクトリを表示
awk -F: '{ print $1, $6 }' /etc/passwd
カンマ , で区切ると出力時にスペースが入ります。
任意の文字を挟みたい場合は文字列を連結します。
# "ユーザー名 -> ホームディレクトリ" の形式で表示
awk -F: '{ print $1 " -> " $6 }' /etc/passwd
BEGIN と END ブロック
- BEGIN: 最初の行を読む前に一度だけ実行される
- END: 全行を読み終えた後に一度だけ実行される
# 合計行数をカウント
awk 'END { print "合計行数:", NR }' /etc/passwd
# ヘッダーとフッターを付けて表示
awk 'BEGIN { print "=== ユーザー一覧 ===" }
-F: '{ print $1 }'
END { print "=== 以上 ===" }' /etc/passwd
組み合わせる場合は一行で書く
awk -F: 'BEGIN { print "=== ユーザー一覧 ===" } { print $1 } END { print "=== 以上 ===" }' /etc/passwd
組み込み変数
| 変数 | 意味 |
|---|---|
NR | 現在の行番号(Number of Records) |
NF | 現在の行のフィールド数(Number of Fields) |
FS | 入力フィールドの区切り文字(デフォルト: 空白) |
OFS | 出力フィールドの区切り文字 |
$0 | 行全体 |
# 行番号を先頭に付けて表示
awk '{ print NR": "$0 }' /etc/passwd
# フィールド数が7以上の行だけ表示
awk 'NF >= 7 { print }' data.csv
数値の集計
# 2列目の合計を計算
awk '{ sum += $2 } END { print "合計:", sum }' scores.txt
# 平均を計算
awk '{ sum += $2 } END { print "平均:", sum/NR }' scores.txt
実践例:アクセスログの解析
# HTTPステータスコードごとの件数を集計
awk '{ count[$9]++ } END { for (code in count) print code, count[code] }' access.log
# 特定のIPアドレスのアクセスだけ抽出
awk '$1 == "192.168.1.1" { print }' access.log
CSV ファイルの処理
# CSVの2列目と3列目を抽出してタブ区切りで出力
awk -F, 'OFS="\t" { print $2, $3 }' data.csv
# ヘッダー行(1行目)を除いて処理
awk -F, 'NR > 1 { print $1, $2 }' data.csv
練習問題
次のファイル students.csv があるとします。
名前,点数,学年
Alice,85,3
Bob,92,2
Carol,78,3
Dave,65,1
Eve,95,2
問題 1
全生徒の名前(1列目)だけを表示するコマンドを書いてください。ただしヘッダー行は除くこと。
問題 2
点数(2列目)が 80 点以上の生徒の名前と点数を表示してください。
問題 3
全生徒の点数の合計と平均を表示してください。
解答
問題 1
awk -F, 'NR > 1 { print $1 }' students.csv
問題 2
awk -F, 'NR > 1 && $2 >= 80 { print $1, $2 }' students.csv
問題 3
awk -F, 'NR > 1 { sum += $2 } END { print "合計:", sum, "/ 平均:", sum/(NR-1) }' students.csv
awk は覚えることが多いですが、フィールド抽出と集計の基本パターンを押さえるだけで日常のシェル作業が大幅に効率化されます。sed コマンドと組み合わせると、より複雑なテキスト変換も簡単に実現できます。