はじめに
awkはテキスト処理に特化した強力なコマンドであり、ログ解析やデータ加工などで頻繁に使われます。
その中でもifを使った条件分岐は、処理の柔軟性を高める重要な要素です。
しかし初学者にとっては、シェルスクリプトのifとの違いや、awk特有の書き方に戸惑うことが多いです。
本記事ではawkの条件分岐について、つまずきやすいポイントを押さえながら丁寧に解説します。
参考: gawk manual
awkの基本構文
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
cherry 150
EOF
実行コマンド
awk '{ if ($2 > 150) print $1, $2 }' input.txt
実行結果
banana 200
仕組み
| 要素 | 内容 |
|---|---|
| $1 | 1列目(果物名) |
| $2 | 2列目(数値) |
| if ($2 > 150) | 2列目が150より大きいか判定 |
| 条件を満たす行を出力 |
解説
awkは各行を自動で分割し、条件に応じて処理を行います。
この例では「数値が150より大きい行のみ」を抽出しています。
条件式の書き方(比較演算子・論理演算子)
ファイル作成
cat << 'EOF' > input.txt
Alice 25
Bob 17
Charlie 30
EOF
実行コマンド
awk '$2 >= 20 { print $1, $2 }' input.txt
実行結果
Alice 25
Charlie 30
実行コマンド
awk '$2 >= 20 && $2 <= 30 { print $1, $2 }' input.txt
実行結果
Alice 25
Charlie 30
実行コマンド
awk '$2 < 20 || $2 > 30 { print $1, $2 }' input.txt
実行結果
Bob 17
仕組み
| 種類 | 演算子 | 意味 | 例 | 説明 |
|---|---|---|---|---|
| 比較演算子 | >= | 以上 | $2 >= 20 | 2列目(年齢)が20以上 |
| 比較演算子 | < | 未満 | $2 < 20 | 20未満 |
| 論理演算子 | && | AND | $2 >= 20 && $2 <= 30 | 両方の条件を満たす |
| 論理演算子 | || | OR | $2 < 20 || $2 > 30 | 片方の条件を満たす |
解説
awkでは$1や$2で列を指定し、条件式が真の行だけ処理されます。
比較演算子と論理演算子を組み合わせることで柔軟な抽出が可能です。
else の使い方
ファイル作成
cat << 'EOF' > input.txt
Alice 85
Bob 60
Charlie 45
EOF
実行コマンド
awk '{ if ($2 >= 70) { print $1 " : Pass" } else { print $1 " : Fail" } }' input.txt
実行結果
Alice : Pass
Bob : Fail
Charlie : Fail
仕組み
| 要素 | 内容 | 説明 |
|---|---|---|
| $1 | 名前 | 1列目のデータを取得 |
| $2 | 点数 | 2列目のデータを取得 |
| if ($2 >= 70) | 条件式 | 点数が70以上か判定 |
| 出力 | 条件に応じて文字列を表示 | |
| else | 分岐 | 条件を満たさない場合の処理 |
解説
awkは行単位でデータを処理し、列ごとに条件分岐できます。
if-elseを使うことで、データに応じた柔軟な出力が可能です。
else if(多岐分岐)の書き方
ファイル作成
cat << 'EOF' > input.txt
Alice 85
Bob 60
Charlie 45
David 70
EOF
実行コマンド
awk '{ if ($2 >= 80) { print $1 " : Excellent" } else if ($2 >= 70) { print $1 " : Good" } else if ($2 >= 50) { print $1 " : Pass" } else { print $1 " : Fail" } }' input.txt
実行結果
Alice : Excellent
Bob : Pass
Charlie : Fail
David : Good
仕組み
| 記述 | 意味 | 説明 |
|---|---|---|
| $1 | 名前 | 1列目のデータを取得 |
| $2 | 点数 | 2列目のデータを取得 |
| if ($2 >= 80) | 条件1 | 80点以上を判定 |
| else if ($2 >= 70) | 条件2 | 70点以上を判定 |
| else if ($2 >= 50) | 条件3 | 50点以上を判定 |
| else | 最終分岐 | それ以外の処理 |
| 出力 | 条件に応じて文字列を表示 |
解説
awkではelse ifを使うことで複数の条件分岐を順番に評価できます。
条件の上から順に判定されるため、記述順が結果に影響します。
exit・next・nextfile の使い分け
ファイル作成
cat << 'EOF' > input.txt
apple 10
banana 20
skip 0
orange 30
stop 0
grape 40
EOF
ファイル作成
cat << 'EOF' > input2.txt
melon 50
skip 0
peach 60
EOF
実行コマンド
awk '{ if ($1 == "skip") next; print }' input.txt
実行結果
apple 10
banana 20
orange 30
stop 0
grape 40
実行コマンド
awk '{ if ($1 == "stop") exit; print }' input.txt
実行結果
apple 10
banana 20
skip 0
orange 30
実行コマンド
awk '{ if ($1 == "skip") nextfile; print }' input.txt input2.txt
実行結果
apple 10
banana 20
melon 50
仕組み
| キーワード | 動作範囲 | 挙動 | 使用ケース |
|---|---|---|---|
| next | 行単位 | 現在の行をスキップして次の行へ | 特定の行だけ無視したい |
| exit | 全体 | 処理を完全に終了する | 条件成立で即終了したい |
| nextfile | ファイル単位 | 現在のファイルをスキップして次のファイルへ | ファイルごと飛ばしたい |
解説
nextは「その行だけ飛ばす」、exitは「完全終了」、nextfileは「ファイル単位でスキップ」という粒度の違いがあります。
用途に応じて使い分けることで効率的なテキスト処理が可能です。
正規表現を使った条件
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
cherry 150
apple pie 300
EOF
実行コマンド
awk '{ if ($1 ~ /^apple/) print $0 }' input.txt
実行結果
apple 100
apple pie 300
仕組み
| 要素 | 内容 |
|---|---|
| $1 | 1列目(単語部分) |
| ~ | 正規表現マッチ演算子 |
| /^apple/ | 「appleで始まる」正規表現 |
| if (...) | 条件に一致した行のみ処理 |
| print $0 | 行全体を出力 |
解説
awkでは~を使うことで正規表現による条件分岐が可能です。
この例では「appleで始まる行」だけを抽出しています。
また、ifを省略して以下のようにも書くことができます。
awk '$1 ~ /^apple/ { print $0 }' input.txt
空値・未定義変数の扱い
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana
orange 0
grape ""
melon 50
EOF
実行コマンド
awk '{ if ($2 == "" ) print $1 ": empty or undefined"; else print $1 ": " $2 }' input.txt
実行結果
apple: 100
banana: empty or undefined
orange: 0
grape: ""
melon: 50
実行コマンド
awk '{ if ($2+0 == 0) print $1 ": zero or empty"; else print $1 ": " $2 }' input.txt
実行結果
apple: 100
banana: zero or empty
orange: zero or empty
grape: zero or empty
melon: 50
仕組み
| 条件式 | 対象データ | 判定内容 | 結果の違い |
|---|---|---|---|
| $2 == "" | banana | フィールド未定義 → 空文字扱い | empty と判定 |
| $2 == "" | grape "" | 文字列として存在 | emptyではない |
| $2+0 == 0 | banana | 未定義 → 0に変換 | zero と判定 |
| $2+0 == 0 | orange 0 | 数値0 | zero と判定 |
| $2+0 == 0 | grape "" | 空文字 → 数値変換で0 | zero と判定 |
解説
awkでは未定義フィールドは空文字として扱われ、数値演算では0に変換される。
そのため「空かどうか」と「数値0かどうか」で判定結果が変わる点に注意が必要。
BEGIN・ENDブロックでの使い方
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
EOF
実行コマンド
awk 'BEGIN { print "=== START ===" } { if ($2 > 150) print $1 } END { print "=== END ===" }' input.txt
実行結果
=== START ===
banana
=== END ===
仕組み
| 要素 | 内容 | 実行タイミング |
|---|---|---|
| BEGIN | 処理開始前に一度だけ実行 | 入力読み込み前 |
| if 文 | 条件に応じて処理を分岐 | 各行ごと |
| $1, $2 | フィールド(列)参照 | 各行処理中 |
| END | 処理終了後に一度だけ実行 | 全行処理後 |
解説
awkは行単位で処理し、BEGINとENDで前後処理を定義できます。
if文を使うことで条件に合うデータだけを柔軟に抽出できます。
数値比較と文字列比較の違い
ファイル作成
cat << 'EOF' > input.txt
10 apple
2 banana
30 cherry
EOF
実行コマンド
awk '$1 > 10 {print $0}' input.txt
実行結果
30 cherry
実行コマンド
awk '$1 > "10" {print $0}' input.txt
実行結果
2 banana
30 cherry
仕組み
| 比較タイプ | 条件式 | 比較方法 | 判定基準 | 結果例 |
|---|---|---|---|---|
| 数値比較 | $1 > 10 | 数値として比較 | 数値の大小 | 30 のみ通過 |
| 文字列比較 | $1 > "10" | 文字列として比較 | 辞書順(ASCII順) | 2, 30 が通過 |
解説
awkは比較対象に数値リテラルを使うと数値比較、文字列を使うと文字列比較になります。
文字列比較では辞書順になるため、数値の大小とは異なる結果になる点に注意が必要です。
シェルスクリプト内での if との違い
ファイル作成
cat << 'EOF' > input.txt
10
20
30
EOF
実行コマンド
awk '{ if ($1 > 15) print $1 }' input.txt
実行結果
20
30
実行コマンド
while read line; do
if [ "$line" -gt 15 ]; then
echo "$line"
fi
done < input.txt
実行結果
20
30
仕組み
| 項目 | awk の if | シェルの if |
|---|---|---|
| 実行場所 | awk 内部 | シェル |
| データ処理 | 行単位で自動処理 | ループが必要 |
| 書き方 | { if (条件) 処理 } | if [ 条件 ]; then ... fi |
| 変数 | $1 などフィールド単位 | $line など変数 |
| 用途 | テキスト処理特化 | 汎用制御 |
解説
awkはテキスト処理に特化しており簡潔に書けるのが特徴です。
シェルのifは柔軟ですが、ループなどの記述が必要になります。
三項演算子(?:)の使い方
ファイル作成
cat << 'EOF' > input.txt
Alice 80
Bob 45
Charlie 60
EOF
実行コマンド
awk '{ if ($2 >= 60) print $1, "Pass"; else print $1, "Fail" }' input.txt
実行結果
Alice Pass
Bob Fail
Charlie Pass
実行コマンド
awk '{ print $1, ($2 >= 60 ? "Pass" : "Fail") }' input.txt
実行結果
Alice Pass
Bob Fail
Charlie Pass
仕組み
| 項目 | 内容 |
|---|---|
| $1 | 1列目(名前) |
| $2 | 2列目(点数) |
| if 文 | 条件に応じて処理を分岐 |
| >= 60 | 合格判定条件 |
| ?: | 三項演算子(条件 ? 真 : 偽) |
| 結果を出力 |
解説
if 文は明示的な分岐、三項演算子は簡潔に条件分岐を書けます。
用途に応じて可読性で使い分けます。
変数の扱いとスコープ
ファイル作成
cat << 'EOF' > input.txt
10
20
30
EOF
実行コマンド
awk '{ if ($1 > 15) { x = $1 * 2 } print $1, x }' input.txt
実行結果
10
20 40
30 60
実行コマンド
awk '{ if ($1 > 15) { y = $1 * 2 } else { y = 0 } print $1, y }' input.txt
実行結果
10 0
20 40
30 60
仕組み
| 項目 | 内容 |
|---|---|
| 変数の宣言 | awkでは事前宣言不要で使用時に自動生成 |
| スコープ | 基本的にスクリプト全体で共有(ブロックローカルではない) |
| if内の変数 | if文内で代入しても外側で参照可能 |
| 未代入時 | 初期値は空文字(数値文脈では0) |
| 上書き | 条件に応じて値が更新され続ける |
解説
awkの変数はブロックスコープを持たず、if文内で定義しても外で使われます。
未代入のまま使うと空(または0)として扱われる点に注意が必要です。
パターン指定と条件分岐の違い
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
apple 300
orange 150
EOF
実行コマンド
awk '$1 == "apple" { print $0 }' input.txt
実行結果
apple 100
apple 300
実行コマンド
awk '{ if ($1 == "apple") print $0 }' input.txt
実行結果
apple 100
apple 300
仕組み
| 項目 | パターン指定 | if 文 |
|---|---|---|
| 記述位置 | パターン部に直接書く | アクション内に書く |
| 書き方 | $1 == "apple" { 処理 } | { if (条件) 処理 } |
| 実行タイミング | 条件が真のときのみ処理実行 | 常にブロック実行し中で判定 |
| 可読性 | シンプルで短い | 複雑な条件に向く |
| 拡張性 | やや低い | 高い(else など使える) |
解説
パターン指定は簡潔に書けるのが強みで、単純な条件に向いています。
一方、if文は柔軟で複雑な分岐処理を行う場合に適しています。
ワンライナーでの書き方
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
grape 300
EOF
実行コマンド
awk '$2 > 150 { print $1 }' input.txt
実行結果
banana
grape
実行コマンド
awk '{ if ($2 > 150) print $1 }' input.txt
実行結果
banana
grape
仕組み
| 要素 | 内容 |
|---|---|
| $2 > 150 | 2列目の値が150より大きいか判定 |
| { print $1 } | 条件を満たした行の1列目を出力 |
| パターン形式 | 条件のみ書くと真のとき実行される |
| if文形式 | 明示的に条件分岐を書く方法 |
解説
awkでは条件を直接書くことで簡潔にif文の代わりになります。
複雑な条件の場合はifを使うと可読性が上がります。
配列を組み合わせた条件分岐
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
apple 120
banana 180
EOF
実行コマンド
awk '{
price[$1] += $2
}
END {
for (item in price) {
if (price[item] > 250) {
print item, price[item]
}
}
}' input.txt
実行結果
banana 380
仕組み
| 要素 | 内容 |
|---|---|
| $1 | 商品名(キー) |
| $2 | 数値(加算対象) |
| price[$1] += $2 | 配列に合計値を格納 |
| for (item in price) | 配列をループ |
| if (price[item] > 250) | 条件分岐でフィルタ |
| 条件に合うデータを出力 |
解説
awkの配列で集計し、ENDブロック内のif文で条件に合う要素だけを抽出しています。
キーごとの合計値に対して柔軟な条件分岐が可能です。
配列名とキーに使用する変数は任意の文字列に変更可能です。
条件分岐でよくあるエラーと対処法
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
EOF
実行コマンド
awk '{ if ($2 > 150) print $1 }' input.txt
実行結果
banana
実行コマンド
awk '{ if ($2 = 150) print $1 }' input.txt
実行結果
apple
banana
orange
仕組み
| 項目 | 正しい書き方 | 誤り例 | 内容 |
|---|---|---|---|
| 比較演算子 | == | = | == は比較、= は代入 |
| 条件式 | $2 > 150 | $2 = 150 | 数値比較か代入かで結果が変わる |
| 出力 | print $1 | 同じ | 条件が真のときのみ実行 |
解説
awkでは = は代入になるため、条件式で使うと常に真になりやすいです。
比較には必ず == を使う必要があります。
デバッグ方法(printデバッグなど)
ファイル作成
cat << 'EOF' > input.txt
apple 100
banana 200
orange 150
EOF
実行コマンド
awk '{ if ($2 > 150) print $1 }' input.txt
実行結果
banana
実行コマンド
awk '{ print "DEBUG:", $1, $2; if ($2 > 150) print "MATCH:", $1 }' input.txt
実行結果
DEBUG: apple 100
DEBUG: banana 200
MATCH: banana
DEBUG: orange 150
仕組み
| 要素 | 内容 | 目的 |
|---|---|---|
| $1, $2 | フィールド(1列目・2列目) | データの参照 |
| if ($2 > 150) | 条件分岐 | 条件に一致する行を判定 |
| 出力処理 | 結果やデバッグ情報を表示 | |
| "DEBUG:" | デバッグ用文字列 | 処理の途中確認 |
| "MATCH:" | 条件通過時の目印 | 条件成立の確認 |
解説
printを使って途中経過を出力することで、条件分岐の動きを可視化できます。
特にawkではステップ実行がないため、この方法が基本的なデバッグ手法です。
可読性を高める書き方(コーディング規約)
ファイル作成
cat << 'EOF' > input.txt
Alice 85
Bob 45
Charlie 72
David 30
EOF
実行コマンド
awk '{if ($2 >= 60) print $1,"Pass"; else print $1, "Fail"}' input.txt
実行結果
Alice Pass
Bob Fail
Charlie Pass
David Fail
実行コマンド
awk '{
if ($2 >= 60) {
print $1, "Pass"
} else {
print $1, "Fail"
}
}' input.txt
実行結果
Alice Pass
Bob Fail
Charlie Pass
David Fail
仕組み
| 要素 | 説明 |
|---|---|
| $1 | 1列目(名前) |
| $2 | 2列目(点数) |
| if ($2 >= 60) | 条件判定(60点以上で合格) |
| 結果の出力 | |
| {} | 処理ブロックを明確化 |
| 改行・インデント | 可読性向上(規約的に重要) |
解説
awkのif文は改行とブロックを使うことで条件と処理の対応関係が明確になります。
短く書けても、保守性を考えると整形された書き方が推奨されます。
awkとifを使いこなすための実践ポイント
awkとifの組み合わせはシンプルながら非常に強力です。
基本構文と条件分岐の違いを理解し、実践的な例で繰り返し使うことで確実に身につきます。
特にパターン指定との使い分けや、数値と文字列の違いを意識することが上達の近道です。
最初は短いワンライナーから始め、徐々に複雑な処理に挑戦していくと理解が深まります。
awkとif以外の使い方の記事
以下のリンクはawkコマンドの記事です
網羅的に学びたい方はぜひご活用ください

