「sedコマンドの書き方が複雑で、毎回ネットで調べてしまう」
サーバーの構築や設定変更で、設定ファイルの特定の文字列をまとめて置換したい場面は頻繁に発生します。
この記事では、テキストを加工する
sed(セド)コマンド の実践的な使い方を解説します。基本的な文字列置換から、ファイルを直接書き換える
-i オプション、正規表現を使った高度な置換、find との組み合わせによる複数ファイルの一括置換まで、実務で使える手順をまとめました。sedコマンドとは?(ストリームエディタの基本概念)
sed は「Stream Editor(ストリームエディタ)」の略で、ファイルをviなどのエディタで開かずに、コマンドラインからテキストを加工できるツールです。最大の特徴は、ファイルを開かずに文字列の置換・削除・追加ができる点です。1つのファイルに対してはもちろん、シェルスクリプトに組み込んで大量のファイルを自動処理することもできます。
基本的な文字列置換(s/検索/置換/)
sed の最も基本的な使い方は、s(substitute:置換)コマンドです。書式は s/検索文字列/置換文字列/ です。1. 最初にマッチした文字列だけを置換する
デフォルトでは、各行の中で最初にマッチした文字列だけが置換されます。結果は画面に表示され、元のファイルは変更されません。# old を new に置換して表示する(各行の最初のマッチのみ) $ sed 's/old/new/' sample.txt
2. 行内のすべてのマッチを置換する(gフラグ)
1行の中に同じ文字列が複数回出現する場合、すべて置換するには末尾にg(global)フラグを付けます。実務ではほとんどの場合 g を付けて使います。# old をすべて new に置換する $ sed 's/old/new/g' sample.txt
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
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
2. 特定の文字列を含む行を削除する(d コマンド)
d(delete)コマンドを使うと、パターンにマッチした行を丸ごと削除できます。設定ファイルから不要な行を取り除く時に便利です。# "debug" を含む行を削除して表示する $ sed '/debug/d' sample.txt # コメント行(# で始まる行)を削除して表示する $ sed '/^#/d' /etc/httpd/conf/httpd.conf # 空行を削除して表示する $ sed '/^$/d' sample.txt
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
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
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
正規表現を使った高度な置換
sed では基本正規表現(BRE)が使えます。単純な文字列の置換だけでなく、パターンを使った柔軟な置換ができるのがsedの真価です。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桁以上の数字」にマッチします。# 数字の連続を "XXX" に置換する $ sed 's/[0-9]\+/XXX/g' sample.txt
+ や {} などの量指定子はバックスラッシュ付き(\+、\{n\})で記述します。拡張正規表現を使いたい場合は -E オプション(または -r)を付けてください。3. グループ化と後方参照で文字列を並べ替える(\1)
正規表現でマッチした部分を「後方参照」として再利用できます。\( と \) で囲んだ部分が \1、\2 ... で参照できます。# "2024-01-15" のような日付を "2024/01/15" 形式に変換する $ sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\1\/\2\/\3/g' sample.txt
\1・\2・\3 で参照し、区切り文字をハイフンからスラッシュに変換しています。ログファイルの日付形式を統一したい場面などで使えるテクニックです。行の挿入・追加(i / a コマンド)
置換や削除だけでなく、特定の行の前後にテキストを挿入することもできます。設定ファイルに新しい行を追加する場面で使います。1. 特定の行の前に挿入する(i コマンド)
i(insert)コマンドで、マッチした行の「前」にテキストを挿入します。# "Listen 80" の前にコメント行を挿入する $ sed '/Listen 80/i\# Added by admin' httpd.conf
2. 特定の行の後に追加する(a コマンド)
a(append)コマンドで、マッチした行の「後」にテキストを追加します。# "Listen 80" の後に新しいポート設定を追加する $ sed '/Listen 80/a\Listen 8443' httpd.conf
sedと他のコマンドを組み合わせる(実務Tips)
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' {} \;
パイプで受け取ったテキストをsedで加工する
他のコマンドの出力をパイプでsed に渡し、必要な部分だけを整形することもできます。# ip addr の出力からIPアドレスの行だけを取り出し、余分な空白を除去する $ ip addr show eth0 | sed -n '/inet /p' | sed 's/^ *//'
「sed: -e expression #1」エラーが出た時の対処法
sed を使っていて最もよく遭遇するエラーが「sed: -e expression #1」です。主な原因は以下の2つです。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
本記事のまとめ(sed早見表)
| やりたいこと | コマンド |
|---|---|
| 文字列を置換する(各行最初の1つ) | sed 's/検索/置換/' ファイル名 |
| 文字列をすべて置換する | sed 's/検索/置換/g' ファイル名 |
| ファイルを直接書き換える(バックアップ付き) | sed -i.bak 's/検索/置換/g' ファイル名 |
| 特定の行だけ置換する | sed '5s/検索/置換/' ファイル名 |
| パターンにマッチした行を削除する | sed '/パターン/d' ファイル名 |
| コメント行を削除する | sed '/^#/d' ファイル名 |
| 空行を削除する | sed '/^$/d' ファイル名 |
| コメントアウトする | sed -i.bak '/パターン/s/^/#/' ファイル名 |
| 特定の行だけを表示する | sed -n '10,20p' ファイル名 |
| 複数の操作を同時に実行する | sed -e 's/old/new/g' -e '/^$/d' ファイル名 |
| 設定値を一括で書き換える | sed -i 's/^設定名=.*/設定名=新しい値/' ファイル名 |
| 日付形式を変換する(後方参照) | sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)/\1\/\2/g' ファイル名 |
| 行の前にテキストを挿入する | sed '/パターン/i\挿入テキスト' ファイル名 |
| 行の後にテキストを追加する | sed '/パターン/a\追加テキスト' ファイル名 |
| 複数ファイルを一括置換する | find パス -name "*.拡張子" -exec sed -i.bak 's/検索/置換/g' {} \; |
テキスト処理の基本をもっと体系的に学びたいですか?
sedコマンドはサーバーの設定作業で欠かせないツールですが、実務ではファイル操作・パーミッション・シェルスクリプトの組み合わせなど、体系的な知識が求められます。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
登録10秒/自動返信でDL/合わなければ解除3秒
