sedでファイルの中身を一括置換する方法【Mac/Linux完全対応・正規表現・実用コマンド例集】
ファイル内の文字列を一括で置換したい場面は、エンジニアなら頻繁に遭遇します。「設定ファイルのホスト名を一気に変えたい」「ログファイルから特定のパターンをSQL形式に変換したい」「数百ファイルにわたるコードのAPIエンドポイントを書き換えたい」。
そんなとき強力な武器になるのが sed コマンドです。
ただ、sed には厄介な罠があります。MacとLinuxで挙動が異なるため、ネットで拾ったコマンドがそのまま動かないケースが多いのです。
この記事では、sed の基本構文から、Mac(BSD sed)とLinux(GNU sed)の違い、正規表現を使った複雑な置換、複数ファイルの一括処理まで、実際に動作確認したコマンド例とともに解説します。

この記事で解決できること
- ✅ sedコマンドの基本的な置換構文を理解できる
- ✅ Mac(BSD sed)とLinux(GNU sed)の違いを把握して両対応できる
- ✅ 正規表現を使った高度な置換パターンを習得できる
- ✅ 複数ファイルを一括置換する方法がわかる
- ✅ ファイルをバックアップしながら上書き保存できる
動作確認環境: macOS Sequoia 15.x(BSD sed)/ Ubuntu 22.04 LTS(GNU sed 4.8)
sedとは?基本構文を理解する
sed(Stream EDitor)は、入力ストリームに対してテキスト変換を行うUnixコマンドです。ファイルを直接編集するのではなく、標準入力または指定ファイルの内容を処理して標準出力に結果を出します。
基本的な置換構文
sed 's/置換前/置換後/' ファイル名
s= substitute(置換)コマンド/置換前/置換後/= 区切り文字に/を使うのが一般的(変更可能)
フラグ一覧
| フラグ | 意味 | 例 |
|---|---|---|
g |
行内すべて置換(グローバル) | s/foo/bar/g |
i |
大文字小文字を無視 | s/foo/bar/gi |
数字 |
N番目のマッチのみ置換 | s/foo/bar/2 |
p |
置換した行を出力(-nと組み合わせ) |
-n 's/foo/bar/p' |
基本的なsedコマンド例
特定文字列を置換して標準出力
# ファイルの内容を確認しながら置換(ファイルは変更しない)
sed 's/old_string/new_string/' sample.txt
行内のすべてのマッチを置換(gフラグ)
# gフラグなし:各行の最初のマッチのみ置換
sed 's/foo/bar/' sample.txt
# gフラグあり:各行のすべてのマッチを置換
sed 's/foo/bar/g' sample.txt
実例:
# 入力
echo "foo is foo and foo" | sed 's/foo/bar/'
# 出力: bar is foo and foo
echo "foo is foo and foo" | sed 's/foo/bar/g'
# 出力: bar is bar and bar
区切り文字を変更する
置換対象にスラッシュ(/)が含まれる場合(URLやパスなど)、区切り文字を変更すると可読性が上がります。
# スラッシュをエスケープする方法(読みにくい)
sed 's/\/usr\/local\/bin/\/opt\/bin/' paths.txt
# 区切り文字を | に変更(すっきり)
sed 's|/usr/local/bin|/opt/bin|' paths.txt
# # でも使える
sed 's#/usr/local/bin#/opt/bin#' paths.txt

MacとLinuxでのsedの違い【最重要】
sed を使ううえで最も注意すべき点は、Mac(BSD sed)とLinux(GNU sed)で構文が異なることです。特にファイルを直接書き換える -i オプションの挙動が違います。
-i オプションの違い
| 環境 | バックアップなし上書き | バックアップあり上書き |
|---|---|---|
| Linux(GNU sed) | sed -i 's/old/new/' file |
sed -i.bak 's/old/new/' file |
| Mac(BSD sed) | sed -i '' 's/old/new/' file |
sed -i.bak 's/old/new/' file |
Linuxでは -i の後にスペース不要ですが、MacではBSD sedの仕様で -i '' のようにバックアップ拡張子を必ず指定(空文字列でも可)する必要があります。
# Linux(GNU sed)でファイルを直接書き換え
sed -i 's/old_string/new_string/g' file.txt
# Mac(BSD sed)でファイルを直接書き換え
sed -i '' 's/old_string/new_string/g' file.txt
Linuxで -i '' と書くとエラーになり、MacでLinux構文を使うとバックアップファイルが作られてしまいます。
正規表現の違い
| 機能 | GNU sed(Linux) | BSD sed(Mac) |
|---|---|---|
| グループ(BRE) | \( と \) のみ |
\( と \) のみ |
グループ(ERE・-E) |
( と ) |
( と ) |
| 拡張正規表現 | -E または -r |
-E のみ |
\+(1回以上) |
使用可 | 要 -E |
\w(単語文字) |
使用可 | 未対応の場合あり |
両対応する方法
Macでも brew install gnu-sed で GNU sed(gsed)をインストールできます:
brew install gnu-sed
# インストール後、gsed として使用
gsed -i 's/old/new/g' file.txt
# または PATH に追加してデフォルトを置き換える
export PATH="/opt/homebrew/opt/gnu-sed/libexec/gnubin:$PATH"
シェルスクリプトでクロスプラットフォーム対応する場合の書き方:
#!/bin/bash
if [[ "$OSTYPE" == "darwin"* ]]; then
# Mac
SED="sed -i ''"
else
# Linux
SED="sed -i"
fi
$SED 's/old_string/new_string/g' file.txt
正規表現を使った高度な置換
グループと後方参照
\( と \) で囲んだ部分をグループとして、\1、\2 で参照できます。
実用例:CSVデータをSQL UPDATE文に変換
入力ファイル(phone.csv):
1,09000000000
2,09000000001
3,09000000002
変換後(目標):
update users set mobile_phone = '090-0000-0000' where id = 1;
update users set mobile_phone = '090-0000-0001' where id = 2;
update users set mobile_phone = '090-0000-0002' where id = 3;
sedコマンド:
sed "s/\([^,]*\),\([0-9]\{3\}\)\([0-9]\{4\}\)\([0-9]\{4\}\)/update users set mobile_phone = '\2-\3-\4' where id = \1;/" phone.csv
正規表現の解説:
| パターン | 意味 | マッチする内容 |
|---|---|---|
\([^,]*\) |
カンマ以外の文字の0回以上の繰り返し(グループ1) | 1(ID部分) |
\([0-9]\{3\}\) |
数字3桁(グループ2) | 090 |
\([0-9]\{4\}\) |
数字4桁(グループ3) | 0000 |
\([0-9]\{4\}\) |
数字4桁(グループ4) | 0000 |
置換後の \1〜\4 でそれぞれのグループを参照します。

拡張正規表現(-Eオプション)
-E オプションを使うと、バックスラッシュなしで正規表現グループや + などを使えます:
# 通常の正規表現(エスケープが必要)
sed 's/\([0-9]\{3\}\)-\([0-9]\{4\}\)-\([0-9]\{4\}\)/(\1) \2-\3/' phones.txt
# 拡張正規表現(-E、読みやすい)
sed -E 's/([0-9]{3})-([0-9]{4})-([0-9]{4})/(\1) \2-\3/' phones.txt
電話番号フォーマット変換の例:
echo "090-1234-5678" | sed -E 's/([0-9]{3})-([0-9]{4})-([0-9]{4})/\1\2\3/'
# 出力: 09012345678
echo "09012345678" | sed -E 's/([0-9]{3})([0-9]{4})([0-9]{4})/\1-\2-\3/'
# 出力: 090-1234-5678
行の先頭・末尾への文字列追加
# 各行の先頭に "- " を追加(Markdownリスト変換)
sed 's/^/- /' items.txt
# 各行末尾にセミコロンを追加(SQL文の終端)
sed 's/$/;/' queries.txt
# 先頭と末尾を同時に操作
sed "s/\(.*\)/'\1'/" strings.txt
特定の行のみ置換
# 3行目だけ置換
sed '3s/old/new/' file.txt
# 2〜5行目だけ置換
sed '2,5s/old/new/g' file.txt
# "START" を含む行から "END" を含む行まで置換
sed '/START/,/END/s/old/new/g' file.txt
# 特定パターンを含む行だけ置換
sed '/pattern/s/old/new/g' file.txt
ファイルを直接書き換える(-iオプション)
バックアップなしで上書き
# Linux
sed -i 's/old/new/g' file.txt
# Mac
sed -i '' 's/old/new/g' file.txt
バックアップを作成してから上書き
# バックアップファイル file.txt.bak を作成してから上書き
# Linux
sed -i.bak 's/old/new/g' file.txt
# Mac(同じ構文でOK)
sed -i.bak 's/old/new/g' file.txt
複数ファイルの一括処理
複数ファイルを直接指定
# Linux
sed -i 's/old/new/g' file1.txt file2.txt file3.txt
# Mac
sed -i '' 's/old/new/g' file1.txt file2.txt file3.txt
ワイルドカードで一括処理
# カレントディレクトリの全.txtファイルを置換
# Linux
sed -i 's/old_host/new_host/g' *.txt
# Mac
sed -i '' 's/old_host/new_host/g' *.txt
findと組み合わせてサブディレクトリも含め一括処理
# ディレクトリ配下のすべての.confファイルを置換(Linux)
find /etc/myapp -name "*.conf" -exec sed -i 's/old_host/new_host/g' {} \;
# +を使うと複数ファイルを一度に渡せる(処理が速い)
find /etc/myapp -name "*.conf" | xargs sed -i 's/old_host/new_host/g'
# Mac対応版
find /etc/myapp -name "*.conf" | xargs sed -i '' 's/old_host/new_host/g'

for文と組み合わせる
注意:
for file in $(find ...)はファイル名にスペースが含まれると誤動作します。スペースを含まない環境での簡易用途に限定してください。スペースを含む可能性があるときは-execかwhile readを使ってください。
#!/bin/bash
# シンプルな環境向け(ファイル名にスペースがない場合)
for file in $(find . -name "*.yml"); do
sed -i '' 's/image: myapp:old/image: myapp:new/' "$file"
done
# より安全な書き方(ファイル名にスペースが含まれる場合も対応)
find . -name "*.yml" -exec sed -i '' 's/image: myapp:old/image: myapp:new/' {} \;
実用的なユースケース別コマンド集
URLの一括置換(開発→本番環境切り替え)
# http を https に変更
sed -i '' 's|http://example.com|https://example.com|g' config.txt
# ステージング環境から本番環境に切り替え
sed -i '' 's|staging.example.com|www.example.com|g' *.conf
空行の削除
# 空行を削除
sed '/^$/d' file.txt
# 空白のみの行も削除
sed '/^[[:space:]]*$/d' file.txt
コメントアウト行の削除
# # から始まるコメント行を削除
sed '/^#/d' file.txt
# ; から始まるコメント行を削除(.ini形式など)
sed '/^;/d' config.ini
前後の空白を除去
# 先頭の空白を削除
sed 's/^[[:space:]]*//' file.txt
# 末尾の空白を削除
sed 's/[[:space:]]*$//' file.txt
# 前後両方削除
sed 's/^[[:space:]]*//; s/[[:space:]]*$//' file.txt
ログファイルの整形
# IPアドレスをマスキング
sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/xxx.xxx.xxx.xxx/g' access.log
# タイムスタンプ部分を除去
sed 's/\[.*\] //' access.log
設定ファイルの値を書き換え
# KEY=VALUE 形式の設定ファイルで特定のキーの値を変更
sed -i '' 's/^MAX_CONNECTIONS=.*/MAX_CONNECTIONS=100/' app.conf
# ポート番号の変更
sed -i '' 's/^PORT=[0-9]*/PORT=8080/' .env
よくある失敗パターンと対処法
Mac で「Invalid command code」エラーが出る
原因: Linux構文をMacのBSD sedで実行した。
# エラーになる(Mac)
sed -i 's/old/new/' file.txt
# sed: 1: "file.txt": invalid command code f
対処法: -i '' と空文字列を指定する。
sed -i '' 's/old/new/' file.txt
置換後に想定外の改行が入る
原因: Macでの -i 後の引数の渡し方の問題。
対処法: sed -i '' と '' の間にスペースを入れる。または gsed を使う。
バックスラッシュが効かない
原因: シングルクォートの中でバックスラッシュエスケープが解釈されない。
# 意図通りに動かない場合
sed 's/\t/ /' file.txt # タブを4スペースに変えたい
# 解決策1: $'...' 構文でリテラルのタブを使う
sed "s/$(printf '\t')/ /" file.txt
# 解決策2: Perl を使う(より強力)
perl -pi -e 's/\t/ /g' file.txt
まとめ
sedコマンドの一括置換について解説しました。
- Mac(BSD sed)とLinux(GNU sed)の最大の違いは
-iオプションの構文。Macはsed -i ''、Linuxはsed -iと覚えておく - 正規表現のグループは
\(と\)で囲み、後方参照は\1〜\9で使える - 複数ファイルの一括処理には
find | xargs sedの組み合わせが強力 - 本番ファイルを書き換える前は必ず
-i.bakでバックアップを作成する習慣をつける
両環境で使うスクリプトを書く場合は gsed のインストールか OS 判定を入れておくと安心です。

