32blogby StudioMitsu

sed・awk実践ガイド:テキスト加工の定番コンビ

sedの置換・削除・挿入とawkの列抽出・集計・条件処理を実例で解説。モダン代替のsdも紹介。

13 min read
sedawkCLILinuxbashtext-processing
目次

「設定ファイルの値を一括で書き換えたい」「CSV から必要な列だけ抜き出して合計を出したい」「ログから特定パターンの行を除去したい」

こういった テキスト加工 の場面で登場するのが sedawk だ。どちらもパイプラインで活躍するフィルタコマンドだが、得意分野がはっきり違う。

この記事では sed と awk の基本から実践パターン、さらに両者を組み合わせたワークフローまで解説する。

sedとawk:何が違うのか

一言で整理するとこうなる。

sedawk
正式名称Stream Editorパターンスキャンと処理言語
得意なこと行単位のテキスト変換(置換・削除・挿入)列指向のデータ処理(抽出・計算・集計)
考え方「テキストを書き換える」「テキストからデータを取り出す」
典型的な用途設定ファイルの値変更、ログの整形CSV/TSV の集計、アクセスログ解析

どちらもパイプラインの中で | を挟んで使うフィルタコマンドという点では同じだ。sed は 変換 に強く、awk は 抽出と計算 に強い。この使い分けを頭に入れておくと、どちらを使うべきか迷わなくなる。

sed の基本操作

sed は「ストリームエディタ」の名のとおり、テキストを1行ずつ読んで変換し、結果を出力するコマンドだ。

置換

最も使う操作が s(substitute)コマンドによる置換だ。

bash
# 各行で最初にマッチしたものだけ置換
sed 's/old/new/' file.txt

# 各行のすべてのマッチを置換(g フラグ)
sed 's/old/new/g' file.txt

# ファイルを直接編集(-i オプション)
sed -i 's/old/new/g' file.txt

行指定と範囲指定

bash
# 3行目だけ置換
sed '3s/old/new/' file.txt

# 2行目から5行目を置換
sed '2,5s/old/new/g' file.txt

# 最終行だけ置換
sed '$s/old/new/' file.txt

行の削除・挿入・出力

bash
# パターンにマッチする行を削除
sed '/pattern/d' file.txt

# パターンにマッチした行の後に挿入
sed '/pattern/a\new line' file.txt

# パターンにマッチした行の前に挿入
sed '/pattern/i\new line' file.txt

# 特定範囲の行だけ出力(-n と p の組み合わせ)
sed -n '10,20p' file.txt

複数操作と区切り文字

bash
# 複数の置換を一度に実行
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt

# 区切り文字を変更(パスやURLの操作で便利)
sed 's|/usr/local|/opt|g' config.txt

区切り文字は / 以外にも | # @ などが使える。パスを扱うときに / をエスケープしなくて済むので覚えておくと便利だ。

sed 実践パターン

設定ファイルの一括書き換え

サーバー移行やデプロイ時に設定値を一括で変更するケースだ。

bash
# .env ファイルの DB_HOST を書き換え
NEW_HOST="db-prod.example.com"
sed -i "s/DB_HOST=.*/DB_HOST=${NEW_HOST}/" .env

# 特定行をコメントアウト
sed -i 's/^PermitRootLogin yes/# PermitRootLogin yes/' /etc/ssh/sshd_config

# コメントを解除
sed -i 's/^# *PermitRootLogin/PermitRootLogin/' /etc/ssh/sshd_config

ログファイルのクリーニング

bash
# 空行を除去
sed '/^$/d' file.txt

# 先頭と末尾の空白を除去
sed 's/^[[:space:]]*//;s/[[:space:]]*$//' file.txt

# ANSIエスケープシーケンス(色コード)を除去
sed 's/\x1b\[[0-9;]*m//g' colored-output.txt

バッチ処理(find との組み合わせ)

bash
# プロジェクト内の全 .txt ファイルで年号を一括置換
find . -name "*.txt" -exec sed -i 's/2025/2026/g' {} +

# .env.example から .env を生成しつつ値を置換
sed 's/DB_PASSWORD=changeme/DB_PASSWORD=s3cur3P@ss/' .env.example > .env

awk の基本操作

awk はテキストを フィールド(列)単位で処理する言語だ。各行を自動的に空白で分割し、$1$2 などでアクセスできる。

なお、gawk 5.4.0 ではデフォルトの正規表現エンジンが MinRX に変更された。完全 POSIX 準拠になったため、従来の GNU 拡張に依存していたパターンは動作が変わる可能性がある。従来のエンジンを使いたい場合は環境変数 GAWK_GNU_MATCHERS=1 を設定する。

列の抽出

bash
# 1列目と3列目を出力
awk '{print $1, $3}' data.tsv

# 区切り文字を指定(CSV の場合)
awk -F',' '{print $1, $2}' data.csv

# 行全体を出力($0 は行全体)
awk '{print $0}' file.txt

パターンマッチと条件

bash
# "error" を含む行だけ出力
awk '/error/ {print $0}' logfile.txt

# 3列目が100より大きい行を出力
awk '$3 > 100 {print $1, $3}' data.txt

# 複数条件の組み合わせ
awk '$3 > 100 && $2 == "active" {print $1, $3}' data.txt

組み込み変数

awk には便利な組み込み変数がある。

変数意味
NR現在の行番号(Number of Records)
NF現在の行のフィールド数(Number of Fields)
FSフィールド区切り文字(Field Separator)
OFS出力時のフィールド区切り文字
bash
# 行番号付きで出力
awk '{print NR": "$0}' file.txt

# 各行のフィールド数を表示
awk '{print NR": "NF" fields"}' data.txt

# 最終フィールドを出力
awk '{print $NF}' data.txt

BEGIN / END ブロックと集計

bash
# ヘッダーとフッターを付ける
awk 'BEGIN {print "Name,Score"} {print $1","$3} END {print "---done---"}' data.txt

# 2列目を合計
awk '{sum += $2} END {print "Total:", sum}' sales.txt

# 平均を計算
awk '{sum += $2; count++} END {print "Average:", sum/count}' sales.txt

printf による出力整形

bash
# 左寄せ20文字、右寄せ10文字(小数点2桁)
awk '{printf "%-20s %10.2f\n", $1, $3}' data.txt

printf は C 言語と同じフォーマット指定子が使える。テーブル形式の出力を作るときに重宝する。

awk 実践パターン

CSV/TSV データの集計

bash
# カテゴリ別の売上合計(連想配列を使用)
# 入力: category,product,amount の CSV
awk -F',' '{
    sales[$1] += $3
}
END {
    for (cat in sales)
        printf "%-15s %10.0f\n", cat, sales[cat]
}' sales.csv
bash
# 最大値・最小値・平均を一度に計算
awk 'BEGIN {max = -999999; min = 999999}
{
    sum += $2
    count++
    if ($2 > max) max = $2
    if ($2 < min) min = $2
}
END {
    printf "Max: %.2f  Min: %.2f  Avg: %.2f\n", max, min, sum/count
}' data.txt

アクセスログ解析

bash
# IPアドレス別のアクセス数(上位10件)
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head -10
bash
# HTTPステータスコード別の集計
# CLF形式: IP - - [date] "method path proto" status size
awk '{print $9}' access.log | sort | uniq -c | sort -rn

出力フォーマット整形

bash
# テーブル形式でユーザー情報を表示
awk -F':' 'BEGIN {
    printf "%-20s %-6s %-6s %s\n", "USER", "UID", "GID", "HOME"
    printf "%-20s %-6s %-6s %s\n", "----", "---", "---", "----"
}
$3 >= 1000 && $3 < 65534 {
    printf "%-20s %-6s %-6s %s\n", $1, $3, $4, $6
}' /etc/passwd

sed + awk の組み合わせ

sed と awk はパイプラインで繋ぐことで真価を発揮する。sed で前処理(整形・フィルタ)→ awk で集計という流れだ。

bash
# CSV のヘッダー行を除去してから3列目を集計
sed '1d' sales.csv | awk -F',' '{sum += $3} END {print "Total:", sum}'
bash
# ログから ERROR 行を抽出し、時刻とメッセージだけ表示
sed -n '/ERROR/p' app.log | awk '{print $1, $2, substr($0, index($0,$5))}'
bash
# /etc/passwd からシェルが bash のユーザーだけ抽出し整形
grep '/bash$' /etc/passwd | awk -F':' '{printf "%-15s UID=%-6s %s\n", $1, $3, $6}'
bash
# syslog から今日のエラーを集計
sed -n "/$(date '+%b %e')/p" /var/log/syslog | awk '/error|fail/ {count[$5]++} END {for (s in count) print count[s], s}' | sort -rn

モダン代替:sd

sd は Rust 製の sed 代替ツールだ。sed の s/old/new/g という構文に比べて、エスケープが少なくシンプルに書ける。

インストール

bash
# WSL 環境なら Linux と同じ
cargo install sd

基本的な使い方

bash
# 標準入力から置換
echo "hello world" | sd 'world' 'earth'

# ファイルを直接編集
sd 'old' 'new' file.txt

sed との比較

操作sedsd
基本置換sed 's/foo/bar/g'sd 'foo' 'bar'
パス置換sed 's|/usr/local|/opt|g'sd '/usr/local' '/opt'
正規表現グループsed 's/\(foo\)/[\1]/g'sd '(foo)' '[$1]'
ファイル編集sed -i 's/foo/bar/g' filesd 'foo' 'bar' file

sd は正規表現にデフォルトで PCRE 風の構文を使うため、\( \) のようなエスケープが不要だ。パスの置換でも区切り文字を変更する必要がない。

bash
# 複数行マッチ(v1.1.0 以降)
sd --across 'start\n.*\nend' 'replaced' file.txt

sed に慣れているなら無理に乗り換える必要はない。ただ、正規表現のエスケープが複雑になりがちなワンライナーでは sd のほうがミスが減る。使い分けの目安としては、シンプルな置換は sd、行指定や複雑なスクリプトは sed というのがバランスが良い。

まとめ

sed と awk はテキスト加工における定番の組み合わせだ。

  • sed — 行単位の置換・削除・挿入。設定ファイルの書き換えやログのクリーニングに最適
  • awk — 列単位の抽出・計算・集計。CSV/TSV の処理やアクセスログ解析に最適
  • sed + awk — パイプラインで繋いで前処理→集計。sed で整形、awk で計算が基本パターン
  • sd — sed の構文が面倒なときのモダン代替。エスケープが少なくシンプル

どちらも50年近い歴史を持つ枯れたツールで、Linux サーバーなら必ずインストールされている。まずは sed の s コマンドと awk の {print $1} から始めて、徐々にパターンを増やしていくのがおすすめだ。

テキスト検索には grep・ripgrep、JSON の加工には jq も合わせて使えると、CLI でのデータ処理がさらに快適になる。コマンド全体の見取り図は CLIツール完全マップ を参照してほしい。