sedコマンドで文字列を置換する方法|-iの一括置換やファイル編集も

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips > sedコマンドで文字列を置換する方法|-iの一括置換やファイル編集も
「設定ファイルの中の文字列を一括で書き換えたいけど、viで1つずつ修正するのは時間がかかりすぎる」
「sedコマンドの書き方が複雑で、毎回ネットで調べてしまう」
サーバーの構築や設定変更で、設定ファイルの特定の文字列をまとめて置換したい場面は頻繁に発生します。
20年以上サーバーを運用してきた現場では、sedなしの設定変更作業は考えられないほど頻繁に使うコマンドです。

この記事では、テキストを加工する sed(セド)コマンド の実践的な使い方を解説します。
基本的な文字列置換から、ファイルを直接書き換える -i オプション、複数の置換ルールを一括実行する -e / -f オプション、正規表現を使った高度な置換、findxargs との組み合わせによる複数ファイルの一括置換まで、RHEL 9.4 / Ubuntu 24.04 LTS で動作確認した実務手順を実行例付きでまとめました。

この記事のポイント

・ sed 's/old/new/g' で行内の全マッチを一括置換できる(RHEL 9.4 で動作確認済み)
・ -i オプションでファイルを直接上書き保存できる(-i.bak でバックアップ付き)
・ -e / -f と正規表現・後方参照で複数の置換ルールを一括実行できる
・ find / xargs と組み合わせると複数ファイルの一括置換も安全に行える


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

sedコマンドとは?(ストリームエディタの基本概念)

sed は「Stream Editor(ストリームエディタ)」の略で、ファイルをviなどのエディタで開かずに、コマンドラインからテキストを加工できるツールです。

動作の流れは次の3ステップです。

・ファイルを1行ずつ読み込む(またはパイプ経由で標準入力を受け取る)
・指定したパターンに一致する部分を変換・削除・追加する
・結果を標準出力に書き出す(-i オプション時はファイルを直接上書き)

最大の特徴は、ファイルを開かずに文字列の置換・削除・追加ができる点です。1行ずつ処理する「ストリーム指向」のため、巨大なログファイルでもメモリを圧迫せずに扱えます。1つのファイルに対してはもちろん、シェルスクリプトに組み込んで大量のファイルを自動処理することもできます。

内部では「パターンスペース」と呼ばれる作業領域に1行分のテキストを読み込み、スクリプトを適用してから標準出力に書き出す処理をファイルの最終行まで繰り返します。この仕組みを理解しておくと、-n オプションや行範囲指定など後述する応用テクニックが直感的にわかるようになります。

viやnanoのような対話型エディタが「ファイルを開いて編集・保存する」のに対し、sedは「コマンド1行でテキスト処理が完結する」ストリーム処理型のツールです。サーバー構築やデプロイ作業の自動化に欠かせない存在です。

sed の主なオプションを整理しておきます。
オプション 説明
-e スクリプト コマンドラインで sed スクリプトを直接指定する。複数回指定することで複数の処理を一括実行できる
-f ファイル名 スクリプトをファイルから読み込む。処理が複雑になったときに管理しやすい
-i[拡張子] ファイルを直接書き換える(in-place)。拡張子を指定するとバックアップが残る(例: -i.bak
-n 自動出力を抑制する。p コマンドと組み合わせてマッチした行だけ出力するときに使う
-E(または -r) 拡張正規表現(ERE)を使用する。BRE より簡潔に書けるため、複雑なパターンに向く

基本的な文字列置換(s/検索/置換/)

sed の最も基本的な使い方は、s(substitute:置換)コマンドです。書式は s/検索文字列/置換文字列/ です。

1. 最初にマッチした文字列だけを置換する

デフォルトでは、各行の中で最初にマッチした文字列だけが置換されます。結果は画面に表示され、元のファイルは変更されません。

# old を new に置換して表示する(各行の最初のマッチのみ) $ sed 's/old/new/' sample.txt # 実行例: 同じ文字が複数あっても最初の1か所だけ置換される $ echo "a:b:a:b" | sed 's/a/X/' X:b:a:b

2. 行内のすべてのマッチを置換する(gフラグ)

1行の中に同じ文字列が複数回出現する場合、すべて置換するには末尾に g(global)フラグを付けます。実務ではほとんどの場合 g を付けて使います。

# old をすべて new に置換する $ sed 's/old/new/g' sample.txt # 実行例: すべてのマッチが置換される $ echo "a:b:a:b" | sed 's/a/X/g' X:b:X:b

実際のサーバー作業での使用例(RHEL 9.4 で動作確認済み):

# httpd.conf の Listen ポートを 80 から 8080 に変更して画面確認 [admin@web01 ~]$ echo "Listen 80" | sed 's/80/8080/' Listen 8080 # IP アドレスを複数箇所で置換する [admin@web01 ~]$ echo "server=192.168.1.10 backup=192.168.1.10" | sed 's/192.168.1.10/10.0.0.1/g' server=10.0.0.1 backup=10.0.0.1

3. 大文字・小文字を無視して置換する(Iフラグ)

I フラグを付けると、大文字・小文字を区別せずにマッチさせることができます(GNU sed)。

# Error / error / ERROR いずれもマッチして warning に置換する $ sed 's/error/warning/gI' sample.txt

ファイルを直接書き換える(-i オプション)

ここまでの例はすべて「結果を画面に表示するだけ」で、元のファイルは変更されません。ファイルそのものを書き換えるには -i(in-place)オプションを使います。

1. バックアップを取りながら書き換える(-i.bak)【推奨】

-i の直後に拡張子を指定すると、変更前のファイルがバックアップとして保存されます。本番サーバーの設定ファイルを変更する際は、必ずこの方法を使ってください。

# httpd.conf の ServerName を書き換え、元ファイルを .bak として保存する $ sed -i.bak 's/ServerName old.example.com/ServerName new.example.com/' /etc/httpd/conf/httpd.conf # バックアップファイルが作成されていることを確認する $ ls /etc/httpd/conf/httpd.conf* /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak # 実行例: 書き換え前後の確認 $ cat /tmp/test.conf server_name=localhost $ sed -i.bak 's/localhost/192.168.1.10/' /tmp/test.conf $ cat /tmp/test.conf server_name=192.168.1.10

2. バックアップなしで直接書き換える(-i)

バックアップが不要な場合は、拡張子を指定せずに -i だけを付けます。

# バックアップなしで直接書き換える $ sed -i 's/old/new/g' sample.txt

【重要】-i オプションの危険性と対策

-i はファイルを直接上書きするため、間違った置換を実行すると元に戻せません。
本番環境では必ず以下の手順を守ってください。

・まず -i なしで実行して、置換結果を画面で確認する
・問題なければ -i.bak でバックアップ付きで実行する
・バックアップファイルで差分を確認する(diff コマンド)

# 手順1:まず画面で確認する(ファイルは変更されない) $ sed 's/old/new/g' /etc/httpd/conf/httpd.conf # 手順2:問題なければバックアップ付きで実行する $ sed -i.bak 's/old/new/g' /etc/httpd/conf/httpd.conf # 手順3:差分を確認する $ diff /etc/httpd/conf/httpd.conf.bak /etc/httpd/conf/httpd.conf

実務で頻出するsedのパターン

1. 特定の行だけを置換する(行番号指定)

s コマンドの前に行番号を指定すると、その行だけが置換対象になります。

# 5行目だけを置換する $ sed '5s/old/new/' sample.txt # 10行目から20行目までを置換する $ sed '10,20s/old/new/g' sample.txt # "START" を含む行から "END" を含む行の範囲で置換する $ sed '/START/,/END/s/old/new/g' sample.txt

2. 特定の文字列を含む行を削除する(d コマンド)

d(delete)コマンドを使うと、パターンにマッチした行を丸ごと削除できます。設定ファイルから不要な行を取り除く時に便利です。

# "debug" を含む行を削除して表示する $ sed '/debug/d' sample.txt # コメント行(# で始まる行)を削除して表示する $ sed '/^#/d' /etc/httpd/conf/httpd.conf # 空行を削除して表示する $ sed '/^$/d' sample.txt # コメント行と空行を同時に削除する(-e で複数指定) $ sed -e '/^#/d' -e '/^$/d' sample.txt

実行例(コメント行・空行を削除して有効な設定行だけを取り出す):

[admin@web01 ~]$ cat /tmp/sample.conf # This is a comment ServerName www.example.com # Another comment ServerPort 443 [admin@web01 ~]$ sed -e '/^#/d' -e '/^$/d' /tmp/sample.conf ServerName www.example.com ServerPort 443

3. 行の先頭・末尾に文字列を追加する

正規表現の ^(行頭)と $(行末)を活用して、各行の先頭や末尾に文字列を追加できます。

# 各行の先頭に "LOG: " を追加する $ sed 's/^/LOG: /' sample.txt # 各行の末尾に " ;done" を追加する $ sed 's/$/ ;done/' sample.txt

4. コメントアウト・アンコメントを一括で行う

設定ファイルの行頭に # を付ける(コメントアウト)/外す(アンコメント)は、サーバー設定でよく行う作業です。

# "Listen 8080" を含む行をコメントアウトする $ sed -i.bak '/Listen 8080/s/^/#/' /etc/httpd/conf/httpd.conf # 行頭の # を外す(アンコメント) $ sed -i.bak 's/^#Listen 8080/Listen 8080/' /etc/httpd/conf/httpd.conf # コメントアウトされているかどうかに関わらず確実に書き換える(#\? パターン) # sshd_config の PasswordAuthentication を no に設定する $ sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config

#\? は「# が0回または1回」にマッチします。コメントアウト済みの行(#PasswordAuthentication yes)も有効な行(PasswordAuthentication yes)も、どちらも1つのsedコマンドで確実に書き換えられる便利なパターンです。

5. 特定の行だけを表示する(-n と p の組み合わせ)

-n オプションと p(print)コマンドを組み合わせると、マッチした行だけを表示できます。grep に似た使い方ですが、行番号指定や正規表現の範囲指定で柔軟に絞り込めるのが強みです。

# 5行目だけを表示する $ sed -n '5p' /etc/httpd/conf/httpd.conf # 10行目から20行目までを表示する $ sed -n '10,20p' /etc/httpd/conf/httpd.conf # "Listen" を含む行だけを表示する $ sed -n '/Listen/p' /etc/httpd/conf/httpd.conf # "START" が登場した行から "END" が登場した行まで表示する(バッチログの1ジョブ抽出) $ sed -n '/\[START\]/,/\[END\]/p' batch.log

6. 複数の操作を同時に実行する(-e)

-e オプションを使うと、複数の置換や削除を1回のコマンドで実行できます。

# old を new に置換し、さらに空行を削除する $ sed -e 's/old/new/g' -e '/^$/d' sample.txt # 複数の文字列を同時に置換する $ sed -e 's/foo/bar/g' -e 's/baz/qux/g' sample.txt

7. ログのクリーニング(実務パターン)

サーバー運用では、ログファイルを解析する前に不要な行を取り除いたり、行末の余分な空白を削除したりするクリーニング作業をよく行います。

# アクセスログから静的ファイル(.css .js .png 等)のリクエスト行を除去する $ sed -E '/\.(css|js|png|jpg|gif|ico)[ "]/d' access.log > filtered.log # 行末の余分なスペース・タブを削除する $ sed -i 's/[[:space:]]*$//' file.txt # Windows 形式の改行コード(\r\n)を Linux 形式(\n)に変換する $ sed -i 's/\r$//' dos_file.txt

8. スクリプトファイルで複数の置換ルールを管理する(-f オプション)

置換ルールが増えてきたら、-f(file)オプションでスクリプトファイルにまとめると管理しやすくなります。コマンドラインが長くなってきたときや、環境構築で毎回同じ置換セットを適用する場合に特に有効です。

# スクリプトファイル(replace.sed)を作成する # 1行につき1つのsedコマンドを記述する $ cat replace.sed s/foo/FOO/g s/bar/BAR/g /^#/d /^$/d # -f オプションでスクリプトファイルを指定して実行する $ sed -f replace.sed sample.txt # ファイルに直接適用する場合は -i と組み合わせる $ sed -i.bak -f replace.sed sample.txt

スクリプトファイルをGitリポジトリで管理しておくと、サーバー構築の手順を再現可能な形で記録できます。複数環境に同じ設定変更を適用する自動化スクリプトにも組み込みやすい方法です。

9. 行番号・範囲指定の応用と否定(!)

行番号や行末($)を使ったアドレス指定は、d コマンドや s コマンドと組み合わせることで実務でよく使う高度な絞り込みが可能になります。

# 最終行($)を削除する $ sed '$d' file.txt # 3行目から最終行まで削除(ヘッダー行1・2行目だけを残す) $ sed '3,$d' file.txt # 偶数行を削除する(GNU sed 専用: 0~2 = 0から始まり2行おき) $ sed '0~2d' file.txt # 奇数行を削除する(GNU sed 専用: 1~2 = 1から始まり2行おき) $ sed '1~2d' file.txt # "START" の行から "END" の行の範囲を削除する $ sed '/START/,/END/d' file.txt

「!」で処理対象を反転させる

! はアドレスの否定を意味し、「マッチしない行だけ処理する」という指定になります。

# 1行目以外をすべて削除(1行目だけを残す) $ sed '1!d' file.txt # "server" を含まない行を削除("server" を含む行だけを残す) $ sed '/server/!d' nginx.conf # 10行目から20行目の範囲外を削除(範囲内だけを残す) $ sed '10,20!d' access.log # "ERROR" を含む行だけを出力する $ sed '/ERROR/!d' app.log

! を使うと grep では書けない「行番号範囲の否定」なども簡潔に記述できます。

正規表現を使った高度な置換

sed では基本正規表現(BRE)が使えます。単純な文字列の置換だけでなく、パターンを使った柔軟な置換ができるのがsedの真価です。

まずよく使うパターンを整理しておきます。

パターン 意味 使用例
. 任意の1文字 sed 's/a.c/XYZ/'
* 直前の文字が0回以上 sed 's/ab*/X/'
^ 行頭 sed 's/^#//'
$ 行末 sed 's/ *$//'
[abc] 文字クラス(a・b・cのいずれか) sed 's/[0-9]//g'
\(…\) グループ化・後方参照(BRE) sed 's/\(foo\)bar/\1baz/'
(…) グループ化・後方参照(ERE: -E) sed -E 's/(foo)bar/\1baz/'
+ 直前の文字が1回以上(ERE。BREでは \+ sed -E 's/[0-9]+/NUM/'

1. 任意の文字列にマッチさせる(.*)

.* は「任意の文字が0回以上」にマッチするパターンです。設定ファイルで「キー名は同じだが値が異なる」行を一括で書き換える時に重宝します。

# "MaxClients" の値が何であっても 256 に書き換える $ sed 's/^MaxClients.*/MaxClients 256/' /etc/httpd/conf/httpd.conf # SELINUX の値を disabled に変更する $ sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

2. 数字にマッチさせる([0-9])

数字だけを対象にする場合は [0-9] を使います。[0-9]\+ で「1桁以上の数字」にマッチします(BRE の場合。ERE では [0-9]+)。

# 数字の連続を "XXX" に置換する(BRE) $ sed 's/[0-9]\+/XXX/g' sample.txt # 同じことを ERE(-E オプション)で書く場合 $ sed -E 's/[0-9]+/XXX/g' sample.txt

3. グループ化と後方参照で文字列を並べ替える(\1, \2, \3)

正規表現でマッチした部分を「後方参照」として再利用できます。\(\) で囲んだ部分が順に \1\2\3 で参照できます(ERE では括弧のバックスラッシュ不要)。

# "2024-01-15" のような日付を "2024/01/15" 形式に変換する(BRE) $ sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\1\/\2\/\3/g' sample.txt # ERE(-E オプション)で同じことを書く(より読みやすい) $ sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\1\/\2\/\3/g' sample.txt # IPアドレスの第4オクテットだけを変更する(192.168.1.10 → 192.168.1.20) [admin@web01 ~]$ echo "address=192.168.1.10" | sed 's/\(192\.168\.1\.\)10/\120/' address=192.168.1.20

この例では、年・月・日をそれぞれ \1\2\3 で参照し、区切り文字をハイフンからスラッシュに変換しています。ログファイルの日付形式を統一したい場面などで使えるテクニックです。

4. 拡張正規表現を使う(-E オプション)

-E オプションを付けると、より書きやすい拡張正規表現(ERE)が使えます。
\(…\) の代わりに (…)\+ の代わりに +\{n\} の代わりに {n} が使えます。さらに | で OR 条件を記述できるのが BRE との大きな違いです。

# 基本正規表現(BRE)での記述 $ sed 's/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/DATE/g' log.txt # 拡張正規表現(ERE)で同じことを書く(-E オプション) $ sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2}/DATE/g' log.txt # ERE の | を使った OR 条件("error" または "warning" を "ALERT" に) $ sed -E 's/error|warning/ALERT/gI' app.log # 1文字以上の空白をアンダースコアに変換する $ sed -E 's/ +/_/g' list.txt

5. Windows の改行コード(CR)を削除する

Windows 形式のテキストファイルを Linux で扱う際、行末に不可視の \r(CR)が混入することがあります。
シェルスクリプトや設定ファイルを Windows 環境で編集した後に Linux で実行するとエラーになる場合、まずこの CR 除去を試してください。

# 行末の CR(\r)を削除する(Windows改行 → Unix改行 変換) $ sed -i 's/\r$//' ファイル名 # 行末の余分な空白も合わせて削除する $ sed -i 's/[[:space:]]*$//' ファイル名

行の挿入・追加・置き換え(i / a / c コマンド)

置換や削除だけでなく、特定の行の前後にテキストを挿入したり、行全体を別のテキストに差し替えることもできます。設定ファイルに新しい行を追加したり、特定の設定行を丸ごと書き換える場面で使います。

1. 特定の行の前に挿入する(i コマンド)

i(insert)コマンドで、マッチした行の「前」にテキストを挿入します。

# "Listen 80" の前にコメント行を挿入する $ sed '/Listen 80/i\# Added by admin' httpd.conf # ファイルの先頭に1行追加する $ sed -i '1i # -*- coding: utf-8 -*-' script.py

2. 特定の行の後に追加する(a コマンド)

a(append)コマンドで、マッチした行の「後」にテキストを追加します。

# "Listen 80" の後に新しいポート設定を追加する $ sed '/Listen 80/a\Listen 8443' httpd.conf # "MaxClients" の後に新しいディレクティブを追加する $ sed -i '/^MaxClients/a MaxRequestsPerChild 4000' /etc/httpd/conf/httpd.conf

3. 行を丸ごと別のテキストで置き換える(c コマンド)

c(change)コマンドを使うと、マッチした行全体を別のテキストに置き換えられます。s コマンドと異なり、行の一部ではなく行全体が対象です。

# "old text" を含む行全体を "new text" に置き換える $ sed '/old text/c\new text' file.txt # 3行目を別のテキストに差し替える $ sed '3c\新しい内容に差し替えた行' file.txt # 設定ファイルの特定ディレクティブ行を丸ごと書き換える $ sed -i.bak '/^ServerName /c\ServerName www.new-example.com' /etc/httpd/conf/httpd.conf

設定ファイルの特定の設定行を値ごと丸ごと書き換えたい場合に便利です。s/^ServerName .*/ServerName 新URL/ と同じ効果ですが、行全体を確実に置き換えたいときは c コマンドの方が意図が明確に伝わります。

sedと他のコマンドを組み合わせる(実務Tips)

Apacheアクセスログから必要な情報だけ抽出する(実践例)

アクセスログの解析前処理でも sed は大活躍します。大量のログから必要なフィールドだけを取り出したり、ノイズ行を除去する処理をシェルから直接実行できます。

# Apacheアクセスログから IPアドレスと日時だけを抽出する [admin@web01 ~]$ sed -E 's/([0-9.]+) .* \[([^]]+)\].*/\1 \2/' /var/log/httpd/access_log | head -3 192.168.1.101 29/May/2026:08:12:34 +0900 192.168.1.102 29/May/2026:08:13:01 +0900 10.0.0.5 29/May/2026:08:13:45 +0900 # 静的ファイル(.css .js .png等)のリクエスト行を除去してから集計する [admin@web01 ~]$ sed -E '/\.(css|js|png|jpg|gif|ico)[ "]/d' /var/log/httpd/access_log > filtered.log # 500エラー行だけを抽出してリクエストパスを確認する [admin@web01 ~]$ grep ' 500 ' /var/log/httpd/access_log | sed -E 's/.*"(GET|POST) ([^ ]+) .*/\1 \2/' GET /api/data POST /submit

後方参照と -E オプションを組み合わせると、ログフォーマットに合わせた柔軟な抽出が可能です。フィルタリングと抽出をワンライナーでまとめたい時にsedが力を発揮します。

find + sed で複数ファイルを一括置換する

ディレクトリ内の複数ファイルに対して同じ置換を行いたい場合、find と組み合わせます。

# /var/www/html/ 以下のすべての .html ファイルで old.example.com を new.example.com に置換する $ find /var/www/html/ -name "*.html" -exec sed -i.bak 's/old.example.com/new.example.com/g' {} \; # xargs を使う方法(大量ファイルで高速) $ find /var/www/html/ -name "*.html" | xargs sed -i.bak 's/old.example.com/new.example.com/g' # ファイル名に空白が含まれる場合は -print0 と xargs -0 を組み合わせる $ find /var/www/html/ -name "*.html" -print0 | xargs -0 sed -i.bak 's/old.example.com/new.example.com/g'

-exec は対象ファイルごとに新しいプロセスを起動しますが、xargs はまとめて渡すためプロセス数が削減され、大量ファイルの処理で高速です。

実行例(複数ファイルへの一括置換):

[admin@web01 ~]$ find /etc/httpd/ -name "*.conf" | xargs grep -l "old_server" /etc/httpd/conf/httpd.conf /etc/httpd/conf.d/ssl.conf [admin@web01 ~]$ find /etc/httpd/ -name "*.conf" | xargs sed -i.bak 's/old_server/new_server/g' [admin@web01 ~]$ find /etc/httpd/ -name "*.conf" | xargs grep "new_server" /etc/httpd/conf/httpd.conf:ServerName new_server /etc/httpd/conf.d/ssl.conf:ServerName new_server

シェルスクリプトから設定ファイルを自動変更する

環境構築スクリプトで設定値を動的に書き換えるパターンです。sed -i はコマンド1行で完結するため、Ansibleやシェルスクリプトへの組み込みに最適です。

# httpd.conf の ServerName を変更する $ sed -i 's/^ServerName .*/ServerName www.example.com/' /etc/httpd/conf/httpd.conf # /etc/ssh/sshd_config: コメント行も含め確実に PasswordAuthentication を no に変更する $ sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config # Postfix の main.cf: myhostname を書き換える $ sed -i "s/^myhostname = .*/myhostname = mail.example.com/" /etc/postfix/main.cf

シェルスクリプトでのテンプレート展開

設定ファイルのプレースホルダーを実際の値に置換するパターンは、環境構築スクリプトでよく使います。テンプレートファイルにプレースホルダー(__変数名__ のような文字列)を書いておき、sed で値を埋め込む方法です。

#!/bin/bash # テンプレートから設定ファイルを生成するスクリプト SERVER_NAME="prod.example.com" DB_HOST="db01.internal" DB_PORT="5432" # パスを含む場合はデリミタを | にして可読性を確保する sed \ -e "s|__SERVER_NAME__|${SERVER_NAME}|g" \ -e "s|__DB_HOST__|${DB_HOST}|g" \ -e "s|__DB_PORT__|${DB_PORT}|g" \ /etc/myapp/config.conf.template > /etc/myapp/config.conf echo "設定ファイルを生成しました"

変数展開を使う場合はシングルクォートではなくダブルクォートで囲む点に注意してください(後述のトラブルシュートも参照)。パスにスラッシュが含まれる場合は |# をデリミタに使うと可読性が上がります。

複数行にまたがる処理(N コマンド)

sed は基本的に1行ずつ処理しますが、N コマンドを使うと次の行をパターンスペースに取り込み、複数行をまとめて処理できます。設定ファイルで行継続文字(\)が使われているケースや、特定ブロックの削除に有効です。

# 特定パターンの行とその次の行を削除する $ sed '/DELETE_HEADER/{N; d}' file.txt # 行末の \ で継続されている2行を1行に結合する $ sed -e '/\\$/{N; s/\\\n//}' config.txt # 改行で終わる「継続行」をすべてつなげて1行にする(実際の設定確認用) $ sed ':a; /\\$/{N; s/\\\n[[:space:]]*/ /; ba}' long_command.sh

複数行処理は sed の中でも難易度が高い領域です。行をまたぐ処理が複雑になる場合は awk に切り替えることも選択肢です。

パイプで受け取ったテキストをsedで加工する

他のコマンドの出力をパイプで sed に渡し、必要な部分だけを整形することもできます。

# ip addr の出力からIPアドレスの行だけを取り出し、余分な空白を除去する $ ip addr show eth0 | sed -n '/inet /p' | sed 's/^ *//'

awkコマンドとの使い分け

sedとよく比較されるのが awk コマンドです。どちらもテキスト処理ツールですが、得意な用途が異なります。

sed:行単位の置換・削除・挿入が得意。パターン一致の書き換えはsedが高速でシンプルに書ける
awk:列(フィールド)単位の抽出・集計・計算が得意。CSVやログの列処理はawkが向いている

「特定の文字列を書き換えるだけ」ならsed、「列を取り出して集計・比較する」ならawk、が基本の使い分けです。設定ファイルや定型テキストの一括置換であれば、ほぼsedで対応できます。

「sed: -e expression #1」エラーが出た時の対処法

sed を使っていて最もよく遭遇するエラーが「sed: -e expression #1」系です。主な原因と対処法を整理します。

1. デリミタの衝突(パスに / が含まれる場合)

置換対象にファイルパスなどスラッシュ(/)を含む文字列がある場合、デリミタと衝突してエラーになります。
解決策は、デリミタを / 以外の文字(#|)に変えることです。

# NG:パスの / がデリミタと衝突する $ sed 's//var/log/old//var/log/new/' sample.txt # OK:デリミタを # に変更する $ sed 's#/var/log/old#/var/log/new#' sample.txt # OK:デリミタを | に変更する $ sed 's|/var/log/old|/var/log/new|' sample.txt

2. 正規表現の特殊文字のエスケープ忘れ

sed はデフォルトで正規表現を使うため、.(ドット)、*(アスタリスク)、[(角括弧)などの特殊文字は、リテラルとして扱いたい場合にバックスラッシュ(\)でエスケープが必要です。

# NG:ドットが任意の1文字として解釈される $ sed 's/192.168.1.1/10.0.0.1/g' hosts.txt # OK:ドットをエスケープする $ sed 's/192\.168\.1\.1/10.0.0.1/g' hosts.txt

3. 置換が効かない時のチェックポイント

コマンドを実行しても変化がない場合、以下を確認してください。

g フラグ忘れ:行内に複数マッチがある場合、フラグなしでは最初の1か所しか置換されない
特殊文字のエスケープ忘れ. * [ \ などはバックスラッシュでエスケープが必要
シングルクォートとダブルクォートの混同:シェル変数を埋め込む時はダブルクォート、それ以外はシングルクォートを使う
Windows 改行コード(\r)の混入:行末に見えない \r があると $ アンカーのマッチが外れる。cat -A^M$ が見えたら要変換

# シェル変数を使う場合はダブルクォートで囲む NEW_SERVER="192.168.1.20" $ sed "s/192\.168\.1\.10/${NEW_SERVER}/" hosts.txt # 制御文字・改行コードを可視化して \r 混入を確認する $ cat -A /etc/httpd/conf/httpd.conf | head -5 # 出力例: 行末に ^M が見えたら \r が混入している # ServerName www.example.com^M$

4. macOS(BSD sed)との違い

macOS の sed は GNU sed とは挙動が異なります。
特に -i オプションは、macOS では拡張子を必須で指定する必要があります(バックアップ不要な場合でも空文字 '' を渡す必要があります)。

# Linux (GNU sed): バックアップ不要な場合 $ sed -i 's/old/new/' ファイル名 # macOS (BSD sed): バックアップ不要な場合でも空文字が必須 $ sed -i '' 's/old/new/' ファイル名 # macOS で GNU sed を使いたい場合は Homebrew でインストールする $ brew install gnu-sed $ gsed 's/old/new/g' ファイル名

5. 変更が反映されない(-i 付け忘れの確認)

コマンドを実行しても元のファイルが変わらない場合、-i オプションの付け忘れが最も多い原因です。-i なしのsedは標準出力に結果を表示するだけで、ファイルを変更しません。

# NG:標準出力に出力されるだけ(ファイルは変わらない) $ sed 's/old/new/g' file.txt new content here # ファイルの中身は変わっていない $ cat file.txt old content here # OK:-i オプションでファイルを直接書き換える $ sed -i 's/old/new/g' file.txt # 本番環境では差分確認してから実行する $ sed 's/old/new/g' file.txt | diff file.txt - $ sed -i.bak 's/old/new/g' file.txt

マッチ自体を確認したい場合は sed -n 's/old/new/gp'p フラグ + -n オプション)で、置換が実際に発生した行だけを表示できます。出力がゼロなら検索文字列が見つかっていないため、パターンを見直してください。

6. 変数が展開されない(シングルクォートの落とし穴)

シェルスクリプトで sed にシェル変数を渡す場合、シングルクォートで囲むと変数が展開されません。変数を含む場合はダブルクォートで囲んでください。

# NG: シングルクォートでは $OLD_TEXT が文字列のまま(変数展開されない) OLD_TEXT="old_server" $ sed 's/$OLD_TEXT/new_server/g' file.txt # OK: ダブルクォートで囲むと変数が展開される $ sed "s/${OLD_TEXT}/new_server/g" file.txt # 変数にスラッシュが含まれる場合は区切り文字を変える FILE_PATH="/etc/nginx/nginx.conf" $ sed "s|__CONFIG__|${FILE_PATH}|g" template.txt

ダブルクォートを使う場合はシェルの特殊文字($`! など)がシェルによって展開される点に注意が必要です。$ をリテラルとして扱いたい場合はエスケープ(\$)してください。

7. 改行を置換後に挿入したい

sed で置換後に改行を挿入したい場合、GNU sed(RHEL / Ubuntu 等の Linux 環境)と BSD sed(macOS)で書き方が異なります。

# GNU sed: \n で改行を挿入できる $ echo "a,b,c" | sed 's/,/\n/g' a b c # BSD sed(macOS): 実際の改行文字を埋め込む $ echo "a,b,c" | sed 's/,/\ /g' # どちらの環境でも使える: a コマンドで行の後に追加する $ echo "foo" | sed '/foo/a\追加する行' foo 追加する行

クロスプラットフォームなスクリプトを書く場合は a コマンドを活用するか、ターゲット環境を明確にしておくことを推奨します。

本記事のまとめ(sed早見表)

やりたいこと コマンド
文字列を置換する(各行最初の1つ) sed 's/検索/置換/' ファイル名
文字列をすべて置換する sed 's/検索/置換/g' ファイル名
ファイルを直接書き換える(バックアップ付き) sed -i.bak 's/検索/置換/g' ファイル名
特定の行だけ置換する sed '5s/検索/置換/' ファイル名
行範囲を指定して置換する sed '10,20s/検索/置換/g' ファイル名
n行目から最終行まで削除する sed '3,$d' ファイル名
偶数行を削除する(GNU sed) sed '0~2d' ファイル名
パターンにマッチした行を削除する sed '/パターン/d' ファイル名
パターンにマッチしない行を削除する(!) sed '/パターン/!d' ファイル名
コメント行を削除する sed '/^#/d' ファイル名
空行を削除する sed '/^$/d' ファイル名
コメントアウトする sed -i.bak '/パターン/s/^/#/' ファイル名
コメント有無に関わらず設定を書き換える sed -i 's/^#\?設定名 .*/設定名 新値/' ファイル名
特定の行だけを表示する sed -n '10,20p' ファイル名
複数の操作を同時に実行する sed -e 's/old/new/g' -e '/^$/d' ファイル名
スクリプトファイルで複数ルールを管理する sed -f replace.sed ファイル名
設定値を一括で書き換える sed -i 's/^設定名=.*/設定名=新しい値/' ファイル名
日付形式を変換する(後方参照) sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\1\/\2\/\3/g' ファイル名
拡張正規表現を使う(-E) sed -E 's/パターン/置換後/g' ファイル名
OR 条件で置換する(ERE) sed -E 's/error|warning/ALERT/g' ファイル名
Windows の CR(\r)を削除する sed -i 's/\r$//' ファイル名
行末のスペース・タブを削除する sed -i 's/[[:space:]]*$//' ファイル名
行の前にテキストを挿入する sed '/パターン/i\挿入テキスト' ファイル名
行の後にテキストを追加する sed '/パターン/a\追加テキスト' ファイル名
行を丸ごと別テキストに置き換える(c) sed '/パターン/c\新しい行' ファイル名
複数ファイルを一括置換する(find) find パス -name "*.conf" -exec sed -i.bak 's/検索/置換/g' {} \;
複数ファイルを一括置換する(xargs) find パス -name "*.conf" | xargs sed -i.bak 's/検索/置換/g'
変数を含む置換(ダブルクォート必須) sed "s/${OLD}/${NEW}/g" ファイル名
特定の行とその次の行を削除する(N コマンド) sed '/パターン/{N; d}' ファイル名
macOS(BSD sed)で直接書き換える sed -i '' 's/検索/置換/g' ファイル名

設定ファイル管理を自動化・効率化したい方へ

sed を使いこなせると、サーバー構築・設定変更のスピードが劇的に上がります。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、「Linuxサーバー構築入門マニュアル(図解60P)」を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。