はじめに
テキスト処理の現場でよく使われるawkは、ログ解析やCSV加工などに強力な力を発揮するツールです。
その中でも正規表現を理解することは、awkを使いこなすうえで避けて通れないポイントです。
しかし初学者にとっては、記号の多さや書式の違いに戸惑いやすい分野でもあります。
この記事では、awkにおける正規表現の基本から実践的な使い方までを、つまずきやすい点を意識しながら丁寧に解説します。
参考:GNU awk
AWKにおける正規表現の基本書式とメタ文字の役割
ファイル作成
cat << 'EOF' > input.txt
apple 123
banana 456
cherry_789
grape-001
EOF
実行コマンド
awk '/[a-z]+ [0-9]+/' input.txt
実行結果
apple 123
banana 456
実行コマンド
awk '/^cherry_[0-9]+$/' input.txt
実行結果
cherry_789
実行コマンド
awk '/-/' input.txt
実行結果
grape-001
仕組み
| 要素 | 書式例 | 役割 | マッチ例 |
|---|---|---|---|
| 文字クラス | [a-z] | 小文字アルファベット1文字 | apple |
| 繰り返し | + | 直前のパターンを1回以上 | 123, abc |
| 行頭 | ^ | 行の先頭に一致 | cherry_789 |
| 行末 | $ | 行の末尾に一致 | cherry_789 |
| 任意文字 | . | 任意の1文字 | a1, b- |
| エスケープ | \_ や \- | 特殊文字を通常文字として扱う | cherry_789, - |
解説
awkでは/正規表現/で行をフィルタし、メタ文字により柔軟なパターンマッチが可能です。
行頭・行末や繰り返しを組み合わせることで、精密な抽出が行えます。
パターンマッチング演算子(~ と !~)による条件抽出
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
grape 150
pineapple 300
EOF
実行コマンド
awk '$1 ~ /apple/' input.txt
実行結果
apple 100
pineapple 300
実行コマンド
awk '$1 !~ /apple/' input.txt
実行結果
banana 200
grape 150
仕組み
| 演算子 | 意味 | 条件例 | 動作 |
|---|---|---|---|
| ~ | 正規表現にマッチ | $1 ~ /apple/ | 文字列に "apple" を含む行を抽出 |
| !~ | 正規表現にマッチしない | $1 !~ /apple/ | "apple" を含まない行を抽出 |
解説
awkの~と!~は正規表現による柔軟なフィルタリングを可能にします。
部分一致ベースで条件抽出できるため、テキスト処理で非常に強力です。
正規表現を用いた特定の列(フィールド)のフィルタリング
ファイル作成
cat << 'EOF' > input.txt
id,name,age
1,Alice,23
2,Bob,17
3,Charlie,30
4,David,15
EOF
実行コマンド
awk -F',' '$3 ~ /^[2-9][0-9]$/ {print $0}' input.txt
実行結果
1,Alice,23
3,Charlie,30
仕組み
| 要素 | 内容 | 説明 |
|---|---|---|
| -F',' | フィールド区切り指定 | カンマ区切りCSVとして処理 |
| $3 | 3列目(age) | フィルタ対象の列 |
| ~ | 正規表現マッチ | 条件一致の判定 |
| /^[2-9][0-9]$/ | 20〜99の数値に一致 | 20歳以上のみ抽出 |
| {print $0} | 行全体を出力 | 条件一致した行を表示 |
解説
awkの正規表現マッチ(~)を使うことで、特定列に対して柔軟なフィルタリングが可能です。
今回は3列目の年齢が20以上の行のみ抽出しています。
メタ文字の「エスケープ処理」とリテラル文字の扱い
ファイル作成
cat << 'EOF' > input.txt
abc$def
abc.def
abc\def
abc*def
EOF
実行コマンド
awk '/abc\$def/' input.txt
実行結果
abc$def
実行コマンド
awk '/abc\.def/' input.txt
実行結果
abc.def
実行コマンド
awk '/abc\\def/' input.txt
実行結果
abc\def
実行コマンド
awk '/abc\*def/' input.txt
実行結果
abc*def
仕組み
| メタ文字 | 意味(正規表現) | エスケープ後 | マッチ対象 |
|---|---|---|---|
| $ | 行末 | \$ | $そのもの |
| . | 任意1文字 | \. | .そのもの |
| \ | エスケープ記号 | \\ | \そのもの |
| * | 0回以上の繰り返し | \* | *そのもの |
解説
awkの正規表現ではメタ文字は特別な意味を持つため、\でエスケープするとリテラル文字として扱えます。
シェルとawkの二重解釈を意識するのがポイントです。
大文字・小文字を区別しないマッチングの設定方法
ファイル作成
cat << 'EOF' > input.txt
Apple
apple
APPLE
Banana
EOF
実行コマンド
awk '/apple/' input.txt
実行結果
apple
実行コマンド
awk '{ if (tolower($0) ~ /apple/) print }' input.txt
実行結果
Apple
apple
APPLE
仕組み
| 項目 | 内容 |
|---|---|
| デフォルト動作 | awk の正規表現は大文字・小文字を区別する |
| 対応方法 | tolower() で小文字に変換して比較 |
| マッチ条件 | $0(行全体)を変換して正規表現と比較 |
| 影響範囲 | 条件式内でのみ大小文字を無視した比較が行われる |
解説
正規表現の比較前に文字列を変換することで、大小文字を意識せずマッチできます。
この方法は環境差異の影響を受けにくく安定して動作します。
変数を利用した柔軟なパターン定義
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
cherry 300
apple 150
banana 250
EOF
実行コマンド
pattern="apple|banana"
awk -v pat="$pattern" '$1 ~ pat {print $0}' input.txt
実行結果
apple 100
banana 200
apple 150
banana 250
実行コマンド
min=150
awk -v m="$min" '$2 >= m {print $0}' input.txt
実行結果
banana 200
cherry 300
apple 150
banana 250
仕組み
| 要素 | 内容 | 説明 |
|---|---|---|
| -v pat="$pattern" | 変数受け渡し | シェル変数をawk内に渡す |
| $1 ~ pat | 正規表現マッチ | 1列目がパターンに一致するか判定 |
| pat="apple|banana" | 動的正規表現 | OR条件を変数で柔軟に定義 |
| $2 >= m | 数値条件 | 別の変数を使った条件式 |
| -v m="$min" | 動的条件 | 数値条件も外部から変更可能 |
解説
awkでは-vで変数を渡すことで、正規表現や条件を動的に変更できます。
これによりスクリプトを書き換えずに柔軟なフィルタリングが可能になります。
gsub関数と正規表現を組み合わせた文字列置換
ファイル作成
cat << 'EOF' > input.txt
apple 123
banana 456
cherry 789
EOF
実行コマンド
awk '{ gsub(/[0-9]+/, "NUM"); print }' input.txt
実行結果
apple NUM
banana NUM
cherry NUM
実行コマンド
awk '{ gsub(/a/, "A"); print }' input.txt
実行結果
Apple 123
bAnAnA 456
cherry 789
仕組み
| 要素 | 内容 |
|---|---|
| awk | テキスト処理ツール |
| gsub | 全一致置換(global substitution) |
| /[0-9]+/ | 数字1回以上の正規表現 |
| /a/ | 文字aに一致 |
| "NUM" / "A" | 置換後の文字列 |
| 行ごとに出力 |
解説
gsubは正規表現にマッチしたすべての文字列を置換します。
awkと組み合わせることで、行単位の柔軟な文字列変換が可能です。
split関数で正規表現を区切り文字として利用するテクニック
ファイル作成
cat << 'EOF' > input.txt
apple,orange;banana grape:melon
dog|cat bird:fish
EOF
実行コマンド
awk -F '[,;:| ]+' '{for(i=1;i<=NF;i++) print $i}' input.txt
実行結果
apple
orange
banana
grape
melon
dog
cat
bird
fish
仕組み
| 要素 | 内容 |
|---|---|
| -F | 区切り文字(フィールドセパレータ)を指定 |
| '[,;:| ]+' | 区切り文字 |
| NF | フィールド数(分割後の要素数) |
| $i | i番目のフィールド(分割された値) |
| for文 | すべてのフィールドを順に出力 |
解説
awkでは-Fに正規表現を指定することで、複数の区切り文字をまとめて扱える。
split相当の処理を簡潔に書けるのが強み。
論理演算子と正規表現の併用
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
apple 300
grape 50
EOF
実行コマンド
awk '$1 ~ /apple|orange/ && $2 > 120' input.txt
実行結果
orange 150
apple 300
仕組み
| 要素 | 内容 |
|---|---|
| $1 ~ /apple|orange/ | 1列目が「apple」または「orange」に一致(正規表現) |
| && | AND条件(両方満たす必要あり) |
| $2 > 120 | 2列目の数値が120より大きい |
| 全体 | 条件をすべて満たす行のみ出力 |
解説
awkでは正規表現と論理演算子を組み合わせることで、柔軟な条件抽出が可能です。
複数条件を同時に評価できるのが強みです。
正規表現でログ解析・CSV加工
ファイル作成
cat << 'EOF' > input.txt
2026-05-01 10:00:00 INFO user=alice action=login
2026-05-01 10:05:23 ERROR user=bob action=upload
2026-05-01 10:10:45 INFO user=carol action=logout
2026-05-01 10:15:12 ERROR user=alice action=download
EOF
実行コマンド
awk '/ERROR/' input.txt
実行結果
2026-05-01 10:05:23 ERROR user=bob action=upload
2026-05-01 10:15:12 ERROR user=alice action=download
実行コマンド
awk '{
for(i=1;i<=NF;i++){
if($i ~ /^user=/){ split($i,u,"=") }
if($i ~ /^action=/){ split($i,a,"=") }
}
print u[2], a[2]
}' input.txt
実行結果
alice login
bob upload
carol logout
alice download
実行コマンド
awk '{
user=""; action="";
for(i=1;i<=NF;i++){
if($i ~ /^user=/){ split($i,u,"="); user=u[2] }
if($i ~ /^action=/){ split($i,a,"="); action=a[2] }
}
print $1","$2","$3","user","action
}' input.txt
実行結果
2026-05-01,10:00:00,INFO,alice,login
2026-05-01,10:05:23,ERROR,bob,upload
2026-05-01,10:10:45,INFO,carol,logout
2026-05-01,10:15:12,ERROR,alice,download
仕組み
| 要素 | 内容 |
|---|---|
| $i ~ /^user=/ | フィールド単位で正規表現マッチ |
| split() | key=value を分割 |
| NF | フィールド数 |
| $1,$2,$3 | 日付・時刻・ログレベル |
| ループ処理 | BSD awkでの安全な抽出方法 |
解説
awk(BSD awk)はmatch()の配列キャプチャが弱いため、split()とループで解析するのが安定。
可搬性を重視するならこの書き方が無難。
BSD版とGNU版(gawk)における正規表現仕様の主な差異と注意点
ファイル作成
cat << 'EOF' > input.txt
apple 123
banana 456
cherry_789
EOF
実行コマンド
awk '/[0-9]+/' input.txt
実行結果
apple 123
banana 456
cherry_789
実行コマンド
gawk '/\w+_[0-9]+/' input.txt
実行結果
-bash: gawk: command not found
実行コマンド
awk '/\w+_[0-9]+/' input.txt
実行結果
仕組み
| 項目 | BSD awk | GNU awk (gawk) |
|---|---|---|
| \w | 非対応 | 対応(英数字+_) |
| \d | 非対応 | 対応(数字) |
| POSIX文字クラス [[:alnum:]] | 対応 | 対応 |
| 拡張正規表現 | 基本のみ | 拡張あり |
| 互換性 | 高い(標準寄り) | 拡張豊富 |
解説
BSD版はPOSIX準拠で機能が限定的なのに対し、gawkは便利な拡張正規表現が使えます。
移植性を重視するならPOSIX記法を使うのが安全です。
awkと正規表現を使いこなすための理解まとめ
awkと正規表現の組み合わせは、最初は難しく感じますが、基本的な考え方を押さえれば一気に視界が開けます。
重要なのは、メタ文字の意味を一つずつ理解し、実際にコマンドを書いて試すことです。
また、フィールド指定や関数との組み合わせによって、単なる文字検索を超えた柔軟なデータ処理が可能になります。
環境差にも注意しながら、少しずつ実践経験を積むことで、awkは強力な武器になります。
![[sed] 実行して理解 指定した範囲の行を削除 文字列のsed](https://running-terminal-commands.com/wp-content/uploads/thumbnail_sed_1920_1080.png.webp)