【awkコマンド早見表】列抽出・区切り文字(-F)・集計計算の実務パターン16選

コマンドリファレンス

こんにちは、Bash玄(ばっしゅげん)です。

ログファイルの解析やCSV・TSVデータの集計、システム監視データの整形作業で、「特定カラムだけを抜き出したい」「条件に合う行だけ抽出して合計や平均を即座に計算したい」という場面は頻繁に訪れます。シェルスクリプトやワンライナーにおいて、テキストの列(フィールド)抽出や数値計算を最も高速かつ柔軟にこなせるのが awk(オーク)コマンドです。

sed が行単位の文字列置換を得意とするのに対し、awk「列(カラム)の切り出し」「条件分岐」「四則演算・集計」「連想配列によるグループ化」に圧倒的な強みを持ちます。

この記事では、awk の基本構文から主要オプション・組み込み変数の早見表、さらに実務でそのままコピペして使える16の実践パターン(列抽出・区切り文字指定・集計計算・フォーマット整形)と初心者が陥りやすい落とし穴まで徹底解説します。

1. 最短で動かす基本構文(列抽出)

awk の基本構文は非常にシンプルで、「パターン(条件)」と「アクション(実行内容)」の組み合わせで構成されます。

# 基本構文:パターンに合致した行に対してアクションを実行する
awk 'パターン { アクション }' 対象ファイル名

# 最も基本的な例:空白区切りの1列目と3列目を表示
awk '{print $1, $3}' server.log

パターンを省略して '{print $1, $3}' と記述すると、すべての行を対象に処理が実行されます。

$0(行全体)と $1〜$NF(フィールド指定)の活用法

(行全体)と 〜$NF(フィールド指定)の活用法

awk では、各行のカラム(フィールド)が特殊な変数に自動代入されます。

  • $0 : 行全体のテキスト
  • $1, $2, $3 … : 1列目、2列目、3列目の値
  • $NF : 現在の行の最後の列(最終列)
  • $(NF-1) : 最後から2番目の列
# 行全体を表示(catと同様の挙動)
awk '{print $0}' data.txt

# 1列目と最終列を表示(列数が変動するログなどで威力を発揮)
awk '{print $1, $NF}' access.log

print 内でカンマ , で変数を区切ると、後述する出力フィールド区切り文字(デフォルトは半角スペース)で結合されて出力されます。

2. awk 主要オプション・組み込み変数一覧

実務で頻繁に使用する awk のコマンドラインオプションと組み込み変数を早見表にまとめました。

主要コマンドラインオプション

オプション機能・役割実用例
-F '区切り文字'入力フィールド区切り文字(FS)を指定awk -F',' '{print $2}' data.csv
-v 変数名=値シェル変数や外部変数を awk スクリプト内に渡すawk -v limit=50 '$3 > limit' log.txt
-f スクリプトファイル長文の awk 処理を別ファイルから読み込んで実行awk -f aggregate.awk access.log

必須の組み込み変数一覧

変数名意味・役割初期値主な活用シーン
NR現在までの累計処理行数(Record Number)1から開始ヘッダー行スキップ(NR > 1)、行番号表示
NF現在行のフィールド総数(Number of Fields)行ごとに変化最終列取得($NF)、カラム欠損チェック
FS入力フィールド区切り文字(Field Separator)半角スペース・タブ-F オプションと同じ(CSV・コロン区切り処理)
OFS出力フィールド区切り文字(Output FS)半角スペースカンマ区切り(CSV)やタブ区切りで再出力
ORS出力レコード(行)区切り文字改行( 複数行を1行に連結出力する際などに変更
FILENAME現在処理中のファイル名複数ファイル集計時にファイル名を付与
FNR現在処理中のファイル内での行番号ファイル毎にリセット複数CSVのヘッダーを一括スキップ(FNR > 1

3. 実務で使える頻出パターン集(コピペ実例16選)

ここからは、システム運用やデータ処理の現場で即座にコピペして使える16の実務実践パターンを5つのカテゴリに分けて紹介します。

3.1 CSV / TSV / スペース区切りファイルの列抽出

【パターン1】カンマ区切り(CSV)の特定カラム抽出
-F',' でカンマを指定して特定列を取得します。

# CSVファイル(data.csv)から 1列目(ID)と 3列目(メールアドレス)を抽出
awk -F',' '{print $1, $3}' data.csv

【パターン2】タブ区切り(TSV)ファイルの列抽出
-F' ' を指定してタブ区切りテキストを処理します。

# TSVファイルから 2列目と 4列目を抽出
awk -F'	' '{print $2, $4}' access_log.tsv

【パターン3】不揃いな空白・連続スペース区切りの列抽出
psdfls -l などのコマンド出力はカラム間に連続するスペースが含まれます。オプションを指定しないデフォルトの awk は、連続する空白やタブを自動的に1つの区切りとして処理するため、崩れずに抽出できます。

# ps aux の出力からユーザー名($1)、PID($2)、CPU使用率($3)を抽出
ps aux | awk '{print $1, $2, $3}'

# df -h の出力からファイルシステム名($1)と使用率($5)を抽出
df -h | awk '{print $1, $5}'

【パターン4】出力区切り文字(OFS)を変更してCSV形式で出力
OFS="," を指定することで、スペース区切りのデータやコロン区切りデータをカンマ区切り(CSV)に変換して出力できます。

# /etc/passwd(コロン区切り)から ユーザー名・UID・シェルをカンマ区切りCSVで出力
awk -F':' -v OFS=',' '{print $1, $3, $7}' /etc/passwd

3.2 条件に合致する行のみを抽出する(パターンマッチ・数値比較)

【パターン5】文字列の完全一致・正規表現マッチによるフィルタリング
特定列の値が一致する行のみを抽出します。==(完全一致)、!=(不一致)、~(正規表現マッチ)、!~(正規表現不一致)が使用できます。

# 1列目が "ERROR" と完全一致する行全体を出力
awk '$1 == "ERROR" {print $0}' app.log

# 2列目に HTTPステータス 5xx 系(500, 502, 503等)が含まれる行を出力
awk '$2 ~ /^50[0-9]/ {print $0}' nginx_access.log

【パターン6】数値比較による閾値フィルタリング
レスポンスタイムやディスク容量など、数値が基準を超える行を抽出します。

# 3列目の応答時間(ミリ秒)が 1000(1秒)以上の行の URL($2)と 時間($3)を表示
awk '$3 >= 1000 {print $2, $3}' api_response.log

【パターン7】複数条件の組み合わせ(AND / OR)
論理積 &&(AND)や論理和 ||(OR)を使って複雑なフィルタリングを行います。

# POSTリクエスト かつ ステータスコードが 400 以上の行を抽出
awk '$1 == "POST" && $4 >= 400 {print $0}' access.log

【パターン8】if / else による条件分岐出力
アクションブロック内で if (条件) ... else ... を使って動的に出力内容を変更します。

# スコアが80点以上なら PASS、それ未満なら FAIL と判定を付与して出力
awk '{
  if ($2 >= 80) {
    status = "PASS"
  } else {
    status = "FAIL"
  }
  print $1, $2, status
}' scores.txt

3.3 BEGIN / END ブロックを使った合計・平均値の計算

BEGIN ブロックはファイル処理開始前に1度だけ実行され、END ブロックは全行の処理完了後に1度だけ実行されます。これらを利用して合計・平均・件数の集計を行います。

【パターン9】特定列の合計値(Sum)を計算

# 2列目の売上数値を合算して合計を出力
awk '{sum += $2} END {print "Total:", sum}' sales.txt

【パターン10】平均値(Average)と行数の集計

# 2列目の平均値を計算(0除算防止チェック付き)
awk '{
  sum += $2
  count++
} END {
  if (count > 0) {
    printf "件数: %d 行 | 平均値: %.2f
", count, sum / count
  }
}' latency.txt

【パターン11】最大値(Max)・最小値(Min)の算出

# 2列目の最大値と最小値を求める(1行目で初期化)
awk 'NR == 1 {
  max = $2; min = $2
} {
  if ($2 > max) max = $2
  if ($2 < min) min = $2
} END {
  print "Max:", max, "Min:", min
}' metrics.txt

3.4 複数ファイルの集計と特定カラムの重複カウント

【パターン12】連想配列を使ったキー別(カテゴリ別)集計
awk の配列は文字列を添字にできる連想配列です。これを使うことで sort | uniq -c をパイプせずに awk 単体で高速集計できます。

# 1列目のHTTPステータスコード(200, 404, 500など)別の出現回数を集計
awk '{count[$1]++} END {for (status in count) print status, count[status]}' status_log.txt

【パターン13】元の並び順を保った重複行の排除(dedup)
!seen[$0]++ は「初めて現れた行のみ真(1)になり出力される」という非常に有名な実務イディオムです。sort -u と異なり元の順序を壊さずに重複行を除去できます。

# 行全体の重複を排除(順序保持)
awk '!seen[$0]++' targets.txt

# 特定カラム(例:2列目のIPアドレス)の重複のみ排除
awk '!seen[$2]++' access.log

【パターン14】複数ファイルのヘッダー除外結合とファイル名の付与
FNR は「そのファイル内での行番号」を表します。複数CSVを結合する際に、2つ目以降のファイルのヘッダー行をスキップできます。

# 1つ目のファイルのヘッダーは含め、2つ目以降のファイルはヘッダー(FNR==1)を除外して結合
awk 'FNR == 1 && NR != 1 {next} {print $0}' data_*.csv

3.5 printfを使ったフォーマット整形(桁揃え・ゼロ埋め)

printf 関数を使うと、C言語スタイルの書式指定で桁揃えやゼロ埋めが可能です。

【パターン15】固定長カラム・左寄せ・右寄せの桁揃え

# 1列目を左寄せ15桁、2列目を右寄せ8桁、3列目を小数点第2位まで整形
awk '{printf "%-15s %8d %10.2f
", $1, $2, $3}' report.txt

【パターン16】ゼロ埋め数値(%05d)とパーセント表記

# 1列目のIDを5桁ゼロ埋め、2列目の数値をパーセント表記で出力
awk '{printf "ID: %05d | 使用率: %5.1f%%
", $1, $2}' metrics.txt

4. よくあるエラー・落とし穴と対処法

awk を使う際に初心者がつまずきやすい代表的な落とし穴と、その回避策を整理しました。

1. 区切り文字に連続スペースが含まれる場合の挙動差

-F' '(明示的に単一スペースを指定)と、オプション未指定(デフォルト)では動作が異なります。

  • デフォルト(未指定) : 連続するスペースやタブをまとめて1つの区切りとみなします(psdf の出力に最適)。
  • -F' ' : 空白1つごとに1列とみなすため、連続スペースがあると空のカラム(空文字列)が生成されて列番号がズレます。

不揃いなスペース区切りのファイルを扱う場合は、-F' ' を指定せずデフォルトのまま実行するのが鉄則です。

2. シェル変数を埋め込む際のクォートの落とし穴

Bashの変数を awk に渡す際、ダブルクォートでスクリプト全体を囲むと $1$2 がシェル側で先に展開されてしまい、意図しない挙動になります。外部変数は必ず -v オプション を使って渡してください。

# NG(危険):$1 がBash側で空文字に展開されて構文エラーになる
TARGET="ERROR"
awk "{if (\$1 == "$TARGET") print \$0}" app.log

# OK(推奨):-v オプションで安全に変数を渡す
TARGET="ERROR"
awk -v target="$TARGET" '$1 == target {print $0}' app.log

3. 1行目のヘッダー行をスキップし忘れる問題

CSVファイルなどを集計する際、1行目のヘッダー文字列(「価格」「合計」など)が計算に含まれると集計結果が不正になったりエラーの原因になります。NR > 1 または FNR > 1 を条件に付与して確実に先頭行をスキップしましょう。

# ヘッダー行(1行目)を除外して2行目以降の数値を合計
awk -F',' 'NR > 1 {sum += $2} END {print "Sum:", sum}' sales.csv

4. 数値比較で意図しない文字列比較になる問題(+0 変換)

awk はフィールドの値が文字列か数値かを自動判定します。データ内にカンマや記号、空白が混入していると「文字列順(辞書順)」で比較され、例えば "100" < "5" のように判定されてしまうことがあります。数値を確実に数値型として扱いたい場合は、+0 を加算するイディオムが有効です。

# $3+0 とすることで強制的に数値として比較演算を行う
awk '$3+0 >= 50 {print $0}' data.txt

5. まとめ & 関連記事

awk コマンドは、列抽出・条件分岐・四則演算・連想配列によるグループ集計までを1行のワンライナーで完結できる強力なテキスト処理ツールです。

  • 列抽出の基本 : $1, $2 で特定列、$NF で最終列、-F',' で区切り文字指定
  • 集計と計算 : sum += $2END {print sum} で合計・平均を即座に算出
  • 安全なスクリプト設計 : シェル変数の受け渡しは -v オプションを使用し、ヘッダー除外は NR > 1 を指定

実務では grep で行を絞り込み、awk で列抽出や計算を行い、sed で置換するといったパイプ連携が非常に効果的です。用途に合わせて適切なコマンドを組み合わせ、日々の業務効率化に役立ててください。

関連コマンド & ピラー記事

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント