【完全リファレンス】Linux awkコマンドの使い方|基本構文から実用例80超まで徹底解説
- 作成日 2026.06.21
- linux
awkはLinuxでテキスト処理の万能ナイフと呼ばれるツールです。CSVの集計、ログの解析、列の抽出、データ変換など、grepやsedを超えた高度な処理がワンライナーで実現できます。
しかし、「コマンド」というよりはプログラミング言語に近い設計のため:
$1$NFなどの記号の意味が分からないBEGINENDブロックの使い方が謎- 配列が普通の配列と違う
- gawk/mawk/BSD awk の違いに振り回される
- 結局 Python や Perl で書いた方が良いのでは?
など、入門で挫折しがちなツールでもあります。
本記事では、awkコマンドの基本構文から応用パターンを、リファレンスとしてまとめ直しました。フィールド変数、パターンマッチング、BEGIN/END、出力フォーマット、配列、関数、CSV処理、ログ解析、80超の実用例、Perl/Pythonとの使い分け、FAQまで完全網羅。この1本をブックマークすれば、awkに関するあらゆる疑問が解決します。
- 1. 結論:今すぐ使える基本パターン10選
- 2. awkコマンドの基本構文
- 3. フィールド変数(最重要)
- 4. 区切り文字(FS/OFS)の変更
- 5. パターンマッチング
- 6. 出力:print と printf
- 7. 演算と変数
- 8. 条件分岐(if/else)
- 9. ループ(for、while、do-while)
- 10. 配列
- 11. 文字列関数(よく使う)
- 12. 数値関数
- 13. ユーザー定義関数
- 14. 複数ファイルの処理
- 15. 実用パターン集(80超を厳選)
- 16. awk バリアントの違い
- 17. awk vs sed/perl/python の使い分け
- 18. macOS の awk との違い
- 19. トラブルシューティング
- 20. よくある質問(FAQ)
- 20.1. Q1. awk と sed の違いは?
- 20.2. Q2. awk で空行を無視したい
- 20.3. Q3. 複数のパターンで処理を分岐したい
- 20.4. Q4. awk でファイルを書き換えたい(in-place)
- 20.5. Q5. awk からシェルコマンドを実行したい
- 20.6. Q6. printf で末尾改行を入れたい/入れたくない
- 20.7. Q7. JSON を awk で扱えますか?
- 20.8. Q8. 大量データで遅いです
- 20.9. Q9. awk で正規表現の後方参照は使える?
- 20.10. Q10. awk と csvkit の使い分け
- 20.11. Q11. awkスクリプトをライブラリ化したい
- 20.12. Q12. awk と Python どちらを学ぶべき?
- 21. 参考リンク・関連資料
- 22. まとめ
結論:今すぐ使える基本パターン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行ずつ読み込み、各行に対して以下を繰り返します:
- 行を**フィールド(列)**に分割
- パターンにマッチするか判定
- マッチすればアクション実行
- 次の行へ
for ループ を書かずに、自然に「各行に対する処理」が書ける設計です。
フィールド変数(最重要)
awkは入力行を自動的に空白区切りでフィールド分割します。
主要変数
| 変数 | 意味 |
|---|---|
$0 | 行全体 |
$1 $2 … | 1列目、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
シンプルに値を出力します。
# カンマ区切りで出力(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桁 |
%5d | 5桁右寄せ |
%-5d | 5桁左寄せ |
%05d | 5桁0埋め |
%x %X | 16進数 |
%o | 8進数 |
%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 awk | macOSデフォルト |
| 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(pandas、json等)の方が遥かに楽です。
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)と一部仕様が異なります。
主な違い
| 機能 | gawk | BSD 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管理者なら覚える価値あり。
参考リンク・関連資料
公式ドキュメント
- GNU Awk User’s Guide – gawkの公式マニュアル
- awk(1) manページ(Ubuntu) – awkコマンド公式
- POSIX awk specification – POSIX標準仕様
各実装
- GNU Awk (gawk) 公式 – GNU awk
- mawk GitHub – mawk(高速)
- BWK awk (one true awk) – オリジナルawk
学習リソース
- The AWK Programming Language – 著者本(無料公開)
- Awk One-Liners – ワンライナー集
関連記事(本サイト)
- Linux find オプション一覧 – findコマンド
- Linux grep オプション まとめ – grepコマンド
- crontabの書き方と実用例まとめ – 定期実行
- wget と curl の違いを徹底比較 – HTTPツール
まとめ
awkはLinuxでテキスト処理を行うための強力なツール。要点を再整理します。
- 基本構文:
awk 'パターン {アクション}' ファイル - フィールド変数:
$1〜(列)、$NF(最終列)、NR(行番号)、NF(列数) - 区切り文字:
-F(入力)、OFS(出力)、RS/ORS(レコード区切り) - 特殊ブロック:
BEGIN(最初)、END(最後) - 出力:
print(簡易)、printf(書式指定) - 配列: 連想配列。
!seen[$0]++で重複排除、count[$1]++でグループ集計 - 文字列関数:
length、substr、split、sub/gsub、tolower/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公式マニュアルもあわせてご確認ください。
-
前の記事
vim vs neovim 徹底比較|違い・移行方法・どちらを選ぶべきか2026年版 2026.06.21
-
次の記事
【完全版】tarコマンドの使い方と実用例まとめ|Linux圧縮・アーカイブの基本を徹底解説 2026.06.22
コメントを書く