【完全リファレンス】Linux awkコマンドの使い方|基本構文から実用例80超まで徹底解説

  • 作成日 2026.06.21
  • linux
【完全リファレンス】Linux awkコマンドの使い方|基本構文から実用例80超まで徹底解説

awkはLinuxでテキスト処理の万能ナイフと呼ばれるツールです。CSVの集計、ログの解析、列の抽出、データ変換など、grepsedを超えた高度な処理がワンライナーで実現できます。

しかし、「コマンド」というよりはプログラミング言語に近い設計のため:

  • $1 $NF などの記号の意味が分からない
  • BEGIN END ブロックの使い方が謎
  • 配列が普通の配列と違う
  • gawk/mawk/BSD awk の違いに振り回される
  • 結局 Python や Perl で書いた方が良いのでは?

など、入門で挫折しがちなツールでもあります。

本記事では、awkコマンドの基本構文から応用パターンを、リファレンスとしてまとめ直しました。フィールド変数、パターンマッチング、BEGIN/END、出力フォーマット、配列、関数、CSV処理、ログ解析、80超の実用例、Perl/Pythonとの使い分け、FAQまで完全網羅。この1本をブックマークすれば、awkに関するあらゆる疑問が解決します。


目次

結論:今すぐ使える基本パターン10選

時間がない方向けに、超頻出パターンを先に示します。

# ① 特定列を抽出(1列目)
awk '{print $1}' file.txt

# ② 複数列を抽出(区切り文字スペース)
awk '{print $1, $3}' file.txt

# ③ CSV の特定列
awk -F, '{print $2}' file.csv

# ④ パターンマッチした行のみ処理
awk '/ERROR/ {print $0}' application.log

# ⑤ 列の合計
awk '{sum += $1} END {print sum}' numbers.txt

# ⑥ 平均
awk '{sum += $1; n++} END {print sum/n}' numbers.txt

# ⑦ 行数カウント(wc -l と同等)
awk 'END {print NR}' file.txt

# ⑧ 区切り文字を変換(カンマ→タブ)
awk -F, -v OFS='\t' '{$1=$1; print}' file.csv

# ⑨ 重複除去(sort+uniq相当)
awk '!seen[$0]++' file.txt

# ⑩ ログのレベル別カウント
awk '{count[$3]++} END {for(k in count) print k, count[k]}' app.log

詳細は以下で順に解説します。


awkコマンドの基本構文

awk 'パターン {アクション}' ファイル
  • パターン: 処理対象の行を絞り込む条件(省略時は全行)
  • アクション: パターンにマッチした行で実行する処理(省略時は print

最もシンプルな例

# 全行を表示(cat 相当)
awk '{print}' file.txt
awk '1' file.txt              # パターンを 1(常にtrue)にする省略形

# 1列目だけ表示
awk '{print $1}' file.txt

# 「ERROR」を含む行だけ表示
awk '/ERROR/' file.txt

# 標準入力から処理
cat file.txt | awk '{print $1}'
ps aux | awk '{print $1, $11}'

awk の動作モデル

awkは1行ずつ読み込み、各行に対して以下を繰り返します:

  1. 行を**フィールド(列)**に分割
  2. パターンにマッチするか判定
  3. マッチすればアクション実行
  4. 次の行へ

for ループ を書かずに、自然に「各行に対する処理」が書ける設計です。


フィールド変数(最重要)

awkは入力行を自動的に空白区切りでフィールド分割します。

主要変数

変数意味
$0行全体
$1 $21列目、2列目、…
$NF最後の列
$(NF-1)最後から2番目の列
NF列の総数(Number of Fields)
NR現在の行番号(Number of Records)
FNRファイル内の行番号(複数ファイル時)
FILENAME現在処理中のファイル名
FS入力フィールド区切り文字(Field Separator)
OFS出力フィールド区切り文字(Output FS)
RS入力レコード(行)区切り文字
ORS出力レコード区切り文字

フィールド抽出の例

# 入力例: "Alice 25 Engineer"
echo "Alice 25 Engineer" | awk '{print $1}'   # Alice
echo "Alice 25 Engineer" | awk '{print $2}'   # 25
echo "Alice 25 Engineer" | awk '{print $NF}'  # Engineer(最後の列)
echo "Alice 25 Engineer" | awk '{print NF}'   # 3(列数)

# 複数列
echo "Alice 25 Engineer" | awk '{print $1, $3}'  # Alice Engineer

行番号付き表示

awk '{print NR, $0}' file.txt
# 1 line1
# 2 line2
# ...

区切り文字(FS/OFS)の変更

デフォルトは「空白(スペース・タブ)」ですが、-Fで変更できます。

コマンドラインオプション -F

# カンマ区切り(CSV)
awk -F, '{print $2}' file.csv

# タブ区切り
awk -F'\t' '{print $1}' file.tsv

# コロン区切り(/etc/passwd)
awk -F: '{print $1}' /etc/passwd

# 複数の区切り文字(正規表現)
awk -F'[,;]' '{print $1, $2}' file.txt

スクリプト内でFS設定

awk 'BEGIN {FS=","} {print $1, $2}' file.csv

出力区切り文字(OFS)

# 入力: スペース、出力: タブに変換
awk -F' ' -v OFS='\t' '{$1=$1; print}' file.txt

$1=$1 のトリック: フィールドに「触れる」と awk が行を再構築してOFSで結合します。

RS(レコード区切り)の変更

通常は改行ですが、変更可能:

# 空行で段落区切りされたファイルを処理
awk 'BEGIN {RS=""} {print "Paragraph:", $0}' file.txt

# レコード区切りを「,」にする(CSV全体を1行扱い)
awk 'BEGIN {RS=","} {print NR, $0}' file.csv

パターンマッチング

正規表現パターン

# 「ERROR」を含む行
awk '/ERROR/' application.log

# 「ERROR」または「WARNING」を含む行
awk '/ERROR|WARNING/' application.log

# 否定(マッチしない行)
awk '!/DEBUG/' application.log

# 特定列が正規表現にマッチ
awk '$3 ~ /^ERROR/' application.log

# 否定マッチ
awk '$3 !~ /^DEBUG/' application.log

条件式パターン

# 3列目が「ERROR」と完全一致
awk '$3 == "ERROR"' application.log

# 数値比較
awk '$1 > 100' numbers.txt

# 範囲
awk '$1 >= 100 && $1 <= 200' numbers.txt

# 複合条件
awk '$3 == "ERROR" && $5 > 1000' application.log

範囲パターン

# 「START」から「END」までの行
awk '/START/,/END/' file.txt

# 100行目から200行目
awk 'NR>=100 && NR<=200' file.txt

特殊パターン: BEGIN と END

# 処理開始前: BEGIN
awk 'BEGIN {print "===処理開始==="} {print}' file.txt

# 処理完了後: END
awk '{count++} END {print "Total:", count}' file.txt

# BEGIN と END 両方
awk 'BEGIN {print "Start"; sum=0} 
     {sum += $1} 
     END {print "Total:", sum}' numbers.txt

BEGINは最初に1回だけ、ENDは最後に1回だけ実行されます。


出力:print と printf

print

シンプルに値を出力します。

# カンマ区切りで出力(OFSで結合)
awk '{print $1, $3}' file.txt

# 文字列連結
awk '{print "Name: " $1 " Age: " $2}' people.txt

# 改行を含む
awk '{print $1; print $2}' file.txt

printf(書式指定)

C言語のprintfと同様の書式指定:

# 整形して表示
awk '{printf "%-10s %5d\n", $1, $2}' people.txt
# Alice          25
# Bob            30

# 数値書式
awk '{printf "%.2f\n", $1}' numbers.txt   # 小数点2桁

# 0埋め
awk '{printf "%05d\n", $1}' numbers.txt   # 00123

# 16進数
awk '{printf "0x%X\n", $1}' numbers.txt

主な書式指定子

指定子意味
%s文字列
%d整数
%f浮動小数点
%.2f小数点以下2桁
%5d5桁右寄せ
%-5d5桁左寄せ
%05d5桁0埋め
%x %X16進数
%o8進数
%c文字
%e指数表記

演算と変数

算術演算

# 加減乗除
awk '{print $1 + $2}' file.txt
awk '{print $1 - $2}' file.txt
awk '{print $1 * $2}' file.txt
awk '{print $1 / $2}' file.txt

# 剰余
awk '{print $1 % $2}' file.txt

# べき乗
awk '{print $1 ^ $2}' file.txt

# インクリメント
awk '{count++} END {print count}' file.txt

文字列演算

# 連結(スペースまたは演算子なし)
awk '{print $1 " " $2}' file.txt
awk '{print $1 $2}' file.txt    # スペースなし連結

# 文字列比較
awk '$1 == "alice"' file.txt

# 文字列の繰り返し(あまり使わない)
awk 'BEGIN {while(i++<5) s = s "x"; print s}'   # xxxxx

変数

# 変数定義(型宣言不要)
awk '{name = $1; age = $2; print name, age}' people.txt

# -v で外部から変数渡し
awk -v threshold=100 '$1 > threshold' numbers.txt

# 環境変数を渡す
awk -v user="$USER" 'BEGIN {print "User:", user}'

条件分岐(if/else)

awk '{
    if ($1 > 100) {
        print $0, "高い"
    } else if ($1 > 50) {
        print $0, "中"
    } else {
        print $0, "低い"
    }
}' numbers.txt

ワンライナーでも書ける:

awk '{if ($1 > 100) print "high"; else print "low"}' numbers.txt

三項演算子

awk '{print ($1 > 100 ? "high" : "low")}' numbers.txt

ループ(for、while、do-while)

for ループ

# 列を全て表示
awk '{for(i=1; i<=NF; i++) print $i}' file.txt

# 逆順に表示
awk '{for(i=NF; i>=1; i--) printf "%s ", $i; print ""}' file.txt

# 1〜10を出力
awk 'BEGIN {for(i=1; i<=10; i++) print i}'

while ループ

awk 'BEGIN {
    i = 1
    while (i <= 10) {
        print i
        i++
    }
}'

do-while ループ

awk 'BEGIN {
    i = 1
    do {
        print i
        i++
    } while (i <= 10)
}'

for-in ループ(配列用)

awk '{count[$1]++} END {for(name in count) print name, count[name]}' file.txt

配列

awkの配列は連想配列(ハッシュマップ)です。

基本

# 単純な使用
awk '{count[$1]++} END {for(k in count) print k, count[k]}' file.txt

# 出力例(key名で集計)
# alice 5
# bob 3
# carol 2

配列の要素アクセス

awk 'BEGIN {
    arr["alice"] = 25
    arr["bob"] = 30
    print arr["alice"]   # 25
}'

配列の長さ

awk 'BEGIN {
    arr[1] = "a"
    arr[2] = "b"
    arr[3] = "c"
    print length(arr)    # 3
}'

配列の削除

awk 'BEGIN {
    arr[1] = "a"
    delete arr[1]
    delete arr        # 全削除(gawk)
}'

多次元配列(疑似)

awkでは多次元配列は文字列の連結で表現:

awk 'BEGIN {
    matrix[1,2] = "A"   # 内部的には "1\x1c2" がキー
    matrix[2,3] = "B"
    print matrix[1,2]
    
    for (key in matrix) {
        split(key, idx, SUBSEP)
        print idx[1], idx[2], matrix[key]
    }
}'

文字列関数(よく使う)

length:長さ

awk '{print length($1)}' file.txt
awk '{print length}'           # 行全体の長さ

substr:部分文字列

# 3文字目から
awk '{print substr($1, 3)}' file.txt

# 3文字目から5文字
awk '{print substr($1, 3, 5)}' file.txt

index:位置検索

# "abc" 内で "b" の位置を返す(1始まり)
awk 'BEGIN {print index("abcdef", "cd")}'   # 3

split:文字列分割

# "a,b,c" を arr に分割
awk 'BEGIN {n = split("a,b,c", arr, ","); print n, arr[1], arr[2], arr[3]}'
# 3 a b c

sub / gsub:置換

# 最初の1箇所だけ置換
awk '{sub(/old/, "new"); print}' file.txt

# 全箇所置換
awk '{gsub(/old/, "new"); print}' file.txt

# 特定列のみ置換
awk '{gsub(/old/, "new", $2); print}' file.txt

# 「数値カンマ」を削除
awk '{gsub(/,/, "", $3); print}' file.txt

match:正規表現マッチ

awk '{
    if (match($0, /[0-9]+/)) {
        print "Match at:", RSTART, "Length:", RLENGTH
        print "Matched:", substr($0, RSTART, RLENGTH)
    }
}' file.txt

tolower / toupper:大小文字変換

awk '{print tolower($0)}' file.txt
awk '{print toupper($0)}' file.txt

sprintf:書式化文字列

awk '{s = sprintf("%-10s %5d", $1, $2); print s}' file.txt

数値関数

# 絶対値、平方根、整数化
awk 'BEGIN {print sqrt(16)}'    # 4
awk 'BEGIN {print int(3.7)}'    # 3
awk 'BEGIN {print abs}' # awkにabsはない(自前実装)

# 三角関数
awk 'BEGIN {print sin(0); print cos(0); print atan2(1, 1)}'

# 対数
awk 'BEGIN {print log(2.71828)}'
awk 'BEGIN {print exp(1)}'

# 乱数(0〜1)
awk 'BEGIN {srand(); print rand()}'

ユーザー定義関数

awk '
function max(a, b) {
    return a > b ? a : b
}

function fact(n) {
    return n <= 1 ? 1 : n * fact(n-1)
}

BEGIN {
    print max(10, 20)    # 20
    print fact(5)        # 120
}
'

複数ファイルの処理

# 複数ファイルを処理(NRは累積、FNRはファイル別)
awk '{print FILENAME, FNR, NR, $0}' file1.txt file2.txt

# ファイル切り替わりで何か処理
awk 'FNR == 1 {print "=== " FILENAME " ==="} {print}' *.log

# 2ファイル目だけ処理(gawk)
awk 'FNR != NR' file1.txt file2.txt   # file2のみ表示

2つのファイルを照合(差分・結合)

# file1にあるキーで file2を絞り込む
awk 'NR==FNR {keys[$1]; next} $1 in keys' file1.txt file2.txt

# file1にあって file2にない行(差分)
awk 'NR==FNR {a[$0]; next} !($0 in a)' file1.txt file2.txt

実用パターン集(80超を厳選)

列の抽出系

# 1列目だけ
awk '{print $1}' file.txt

# 最後の列
awk '{print $NF}' file.txt

# 2〜4列目
awk '{print $2, $3, $4}' file.txt

# 1列目と最後の列
awk '{print $1, $NF}' file.txt

# 全列をタブ区切りで
awk -v OFS='\t' '{$1=$1; print}' file.txt

# 列の入れ替え(1列目と2列目を交換)
awk '{tmp=$1; $1=$2; $2=tmp; print}' file.txt

# 特定列を削除(2列目を削除)
awk '{$2=""; print}' file.txt

集計系

# 合計
awk '{sum += $1} END {print sum}' numbers.txt

# 平均
awk '{sum += $1; n++} END {print sum/n}' numbers.txt

# 最大値
awk 'NR==1 {max=$1} $1>max {max=$1} END {print max}' numbers.txt
awk 'BEGIN {max=-1e10} {if($1>max) max=$1} END {print max}' numbers.txt

# 最小値
awk 'BEGIN {min=1e10} {if($1<min) min=$1} END {print min}' numbers.txt

# カウント
awk 'END {print NR}' file.txt

# 条件付きカウント
awk '/ERROR/ {count++} END {print count}' app.log

# グループ別合計
awk '{sales[$1] += $2} END {for(name in sales) print name, sales[name]}' sales.txt

# 平均(グループ別)
awk '{sum[$1] += $2; n[$1]++} END {for(k in sum) print k, sum[k]/n[k]}' data.txt

CSV処理系

# CSVから2列目を抽出
awk -F, '{print $2}' file.csv

# CSVヘッダを除外して処理
awk -F, 'NR>1 {print $2}' file.csv

# 特定列の合計
awk -F, 'NR>1 {sum += $3} END {print sum}' file.csv

# CSV → TSV変換
awk -F, -v OFS='\t' '{$1=$1; print}' file.csv > file.tsv

# 値にカンマを含むCSVは要注意(簡易対応)
awk -F'","' '{...}' file.csv

ログ解析系

# ステータスコード集計(Apacheログ)
awk '{count[$9]++} END {for(s in count) print s, count[s]}' access.log

# 1分あたりのアクセス数
awk '{print substr($4, 2, 17)}' access.log | sort | uniq -c

# IPアドレス別アクセス数Top10
awk '{count[$1]++} END {for(ip in count) print count[ip], ip}' access.log | sort -rn | head -10

# 大きなレスポンスサイズ(Top10)
awk '{print $10, $7}' access.log | sort -rn | head -10

# 特定IPからのアクセスのみ抽出
awk '$1 == "192.168.1.100"' access.log

# 5xx エラーのみ
awk '$9 >= 500' access.log

フィルタリング系

# 空行を削除
awk 'NF > 0' file.txt

# コメント行を削除
awk '!/^#/ && NF > 0' config.txt

# 重複行を削除(連続でなくても)
awk '!seen[$0]++' file.txt

# 重複列を含む行のみ表示
awk 'seen[$0]++' file.txt

# 偶数行のみ
awk 'NR % 2 == 0' file.txt

# 奇数行のみ
awk 'NR % 2 == 1' file.txt

# 範囲行
awk 'NR>=10 && NR<=20' file.txt

# 最後の5行(tailと同等)
awk 'BEGIN {n=5} {lines[NR]=$0} END {for(i=NR-n+1; i<=NR; i++) print lines[i]}' file.txt

変換・加工系

# 大文字に変換
awk '{print toupper($0)}' file.txt

# 1列目だけ大文字
awk '{$1=toupper($1); print}' file.txt

# パスからファイル名を取得
echo "/path/to/file.txt" | awk -F/ '{print $NF}'   # file.txt

# 拡張子を取得
echo "file.tar.gz" | awk -F. '{print $NF}'         # gz

# 行番号付け(cat -n と同等)
awk '{printf "%6d  %s\n", NR, $0}' file.txt

# タブをスペースに(unexpand相当)
awk '{gsub(/\t/, "    "); print}' file.txt

出力フォーマット系

# 列を整形して表示
awk '{printf "%-20s %10d\n", $1, $2}' data.txt

# テーブル形式(ヘッダ付き)
awk 'BEGIN {printf "%-20s %10s\n", "Name", "Score"} 
     {printf "%-20s %10d\n", $1, $2}' data.txt

# CSV出力
awk 'BEGIN {OFS=","} {print $1, $2, $3}' data.txt

# Markdown表
awk 'BEGIN {print "| Name | Age |"; print "|------|-----|"} 
     {print "|", $1, "|", $2, "|"}' people.txt

システム情報系

# ps aux でメモリ使用Top10
ps aux | awk 'NR>1 {print $4, $11}' | sort -rn | head -10

# df 出力をパース
df -h | awk 'NR>1 {print $1, $5, $6}'

# /etc/passwd からユーザー名一覧
awk -F: '{print $1}' /etc/passwd

# ホームディレクトリ一覧
awk -F: '$3 >= 1000 {print $1, $6}' /etc/passwd

# CPUコア数
awk '/^processor/ {n++} END {print n}' /proc/cpuinfo

数学・データ処理系

# 階乗
awk 'BEGIN {n=5; f=1; while(n>0) {f*=n; n--}; print f}'

# フィボナッチ数列
awk 'BEGIN {a=1; b=1; for(i=0;i<10;i++) {print a; t=a+b; a=b; b=t}}'

# 標準偏差
awk '{sum+=$1; sumsq+=$1*$1; n++} 
     END {mean=sum/n; print sqrt(sumsq/n - mean*mean)}' numbers.txt

# 累積合計
awk '{sum+=$1; print $1, sum}' numbers.txt

# 移動平均(3点)
awk '{a[NR]=$1; if(NR>=3) print (a[NR-2]+a[NR-1]+a[NR])/3}' numbers.txt

Git・開発系

# git log の作者集計
git log --format='%an' | awk '{count[$0]++} END {for(a in count) print count[a], a}' | sort -rn

# 各ファイルのコミット数
git log --pretty=format: --name-only | awk 'NF{count[$0]++} END {for(f in count) print count[f], f}' | sort -rn | head -20

# コードの行数カウント(コメント・空行除外、Python例)
find . -name "*.py" -exec awk '!/^\s*#/ && NF' {} + | wc -l

awk バリアントの違い

awkには複数の実装があり、機能差があります。

実装特徴
gawk (GNU awk)機能豊富、Linuxデフォルト
mawk高速、Ubuntu等のデフォルト/etc/alternatives先
BWK awk (nawk, “one true awk”)オリジナルに近い
BSD awkmacOSデフォルト
busybox awk組み込み・コンテナ向け

現在のawkを確認

ls -l $(which awk)
# 例: /usr/bin/awk -> /etc/alternatives/awk
ls -l /etc/alternatives/awk
# /etc/alternatives/awk -> /usr/bin/mawk

gawk独自機能

# 配列のソート
gawk 'BEGIN {arr["c"]=3; arr["a"]=1; arr["b"]=2;
    PROCINFO["sorted_in"] = "@ind_str_asc";
    for(k in arr) print k, arr[k]}'

# strftime(時刻フォーマット)
gawk 'BEGIN {print strftime("%Y-%m-%d %H:%M:%S")}'

# システム時刻
gawk 'BEGIN {print systime()}'

# 大きい数の精度(gawk -M)
gawk -M 'BEGIN {print 2^100}'

gawkを明示的に使う

# パッケージインストール
sudo apt install gawk

# 明示的にgawkを使う
gawk 'BEGIN {print strftime()}'

# シバンで指定
#!/usr/bin/gawk -f

awk vs sed/perl/python の使い分け

使い分け早見表

やりたいこと推奨
単純な置換sed
単純な抽出grep
列単位の処理awk
集計・統計awk
CSV処理awk または csvkit/Python
複雑なロジック・大量データPython Perl
行ベースの単純処理awk

awk が得意なこと

  • 1行1レコードのファイルから列を抽出・集計
  • ログのカラム単位での解析
  • 簡単な条件分岐・集計をワンライナーで

awk が苦手なこと

  • 複雑なデータ構造(深いネスト等)
  • HTML/XML/JSONの解析
  • 大規模な状態管理が必要な処理
  • 文字列処理の高度な操作

このような場合は Python(pandasjson等)の方が遥かに楽です。

awkスクリプトをファイルから実行

# script.awk
#!/usr/bin/awk -f
BEGIN {
    print "Start"
}
{
    print NR, $0
}
END {
    print "End"
}
# 実行
chmod +x script.awk
./script.awk file.txt

# または
awk -f script.awk file.txt

macOS の awk との違い

macOSは BSD awk で、GNU awk(gawk)と一部仕様が異なります。

主な違い

機能gawkBSD awk
gensub✅ あり❌ なし
strftime✅ あり⚠️ 限定的
配列ソート✅ あり(PROCINFO)❌ なし
-i inplace✅ あり❌ なし
nextfile✅ あり✅ あり
多バイト処理✅ あり⚠️ 限定的

macOS でgawkを使う

brew install gawk
# /opt/homebrew/bin/gawk として利用可能
gawk 'BEGIN {print strftime()}'

PATH調整して awk として使う:

echo 'export PATH="/opt/homebrew/opt/gawk/libexec/gnubin:$PATH"' >> ~/.zshrc

トラブルシューティング

$1等が期待通り取れない

入力の区切り文字を確認:

# 区切り文字の確認(タブか?スペースか?)
cat -A file.txt | head -3
# ^I はタブ、$ は行末を意味

必要に応じて -F で明示:

awk -F'\t' '{print $1}' file.txt
awk -F: '{print $1}' /etc/passwd

浮動小数点の精度問題

# 0.1 + 0.2 = 0.3 にならない
awk 'BEGIN {print 0.1 + 0.2}'    # 0.3 と表示されるが内部精度は誤差あり

# printf で桁数を制御
awk 'BEGIN {printf "%.10f\n", 0.1 + 0.2}'   # 0.3000000000

数値が文字列扱いになる

# 文字列比較になってしまう
awk '$1 > "10"' file.txt   # 辞書順比較

# 数値であることを明示(演算してから比較)
awk '$1 + 0 > 10' file.txt

gsub の置換結果がおかしい

特殊文字のエスケープ:

# . はメタ文字(任意1文字)
awk '{gsub(/./, "X"); print}'  # 全文字をXに

# 文字として置換
awk '{gsub(/\./, "X"); print}' # . だけを置換

awk のメモリ問題

巨大ファイルで配列を多用するとメモリ不足になります:

# ❌ メモリ大量消費
awk '{lines[NR]=$0} END {for(i=NR; i>=1; i--) print lines[i]}' huge.log

# ✅ tac コマンドを使う
tac huge.log

よくある質問(FAQ)

Q1. awk と sed の違いは?

  • sed: 行単位のテキスト変換(置換中心)
  • awk: 列単位のテキスト処理(集計・抽出中心)

簡単な置換は sed、列の抽出や集計は awk が向きます。

Q2. awk で空行を無視したい

awk 'NF > 0' file.txt

NF は列数。空行は NF == 0 です。

Q3. 複数のパターンで処理を分岐したい

awk '
/ERROR/ {errors++}
/WARNING/ {warns++}
/INFO/ {info++}
END {
    print "Errors:", errors
    print "Warnings:", warns
    print "Info:", info
}
' application.log

Q4. awk でファイルを書き換えたい(in-place)

GNU awk 4.1以降:

gawk -i inplace '{gsub(/old/, "new")} 1' file.txt

それ以外は一時ファイル経由:

awk '{...}' file.txt > tmp && mv tmp file.txt

Q5. awk からシェルコマンドを実行したい

# 結果を取得
awk 'BEGIN {
    "date" | getline now
    print "Now:", now
}'

# 実行のみ
awk '{system("touch " $1)}' file_list.txt

Q6. printf で末尾改行を入れたい/入れたくない

# 改行あり
awk '{printf "%s\n", $1}'

# 改行なし(連続出力)
awk '{printf "%s ", $1} END {print ""}'

Q7. JSON を awk で扱えますか?

可能ですが非推奨。複雑なJSONは Python や jq を使うべきです:

# 単純なJSONなら awk でも
echo '{"name":"alice"}' | awk -F'"' '{print $4}'   # alice

# 複雑なJSON → jq
echo '{"users":[{"name":"alice"}]}' | jq '.users[0].name'

Q8. 大量データで遅いです

  • mawkを使う(gawkより速い)
  • LC_ALL=C で高速化(ASCII処理に限定)
  • ループ多用なら Python等の方が速い
LC_ALL=C mawk '{...}' huge_file.log

Q9. awk で正規表現の後方参照は使える?

GNU awk の gensub で可能:

gawk '{print gensub(/(\w+)@(\w+)/, "\\2-\\1", "g")}' emails.txt

BSD awk では非対応。

Q10. awk と csvkit の使い分け

# 単純なCSVなら awk で十分
awk -F, '{print $1, $3}' file.csv

# 複雑なCSV(クォート内カンマ、改行)は csvkit
csvcut -c 1,3 file.csv

Q11. awkスクリプトをライブラリ化したい

-f で複数ファイル指定:

awk -f lib.awk -f main.awk data.txt

または @include(gawk):

@include "lib.awk"
{
    ...
}

Q12. awk と Python どちらを学ぶべき?

  • シェルでワンライナー → awk
  • 複雑な処理・データ分析 → Python
  • 両方知っていると最強

awkは数時間で基本を学べるので、Linux管理者なら覚える価値あり。


参考リンク・関連資料

公式ドキュメント

各実装

学習リソース

関連記事(本サイト)


まとめ

awkはLinuxでテキスト処理を行うための強力なツール。要点を再整理します。

  • 基本構文: awk 'パターン {アクション}' ファイル
  • フィールド変数: $1〜(列)、$NF(最終列)、NR(行番号)、NF(列数)
  • 区切り文字: -F(入力)、OFS(出力)、RS/ORS(レコード区切り)
  • 特殊ブロック: BEGIN(最初)、END(最後)
  • 出力: print(簡易)、printf(書式指定)
  • 配列: 連想配列。!seen[$0]++ で重複排除、count[$1]++ でグループ集計
  • 文字列関数: lengthsubstrsplitsub/gsubtolower/toupper
  • awk実装: gawk(Linux標準・高機能)、mawk(高速)、BSD awk(macOS)
  • 使い分け: 単純抽出はgrep、置換はsed、列処理・集計はawk、複雑処理はPython

これらの知識は、ログ解析・CSV処理・サーバー運用・データ加工など、エンジニアの日常業務すべてで活用できます。本記事をブックマークしておけば、いつでも適切なawkコマンドを組み立てられるようになります。


本記事は2026年6月時点の情報をもとに、GNU awk 5.x、mawk 1.3.4、BSD awk(macOS Sonoma/Sequoia)での動作確認に基づき作成しています。awk実装によって一部仕様が異なる場合があるため、最新の情報はGNU Awk公式マニュアルもあわせてご確認ください。