sed -i コマンド情報まとめ
ターミナルの sed -i コマンドについて、オプション情報、macOS と Linux の構文の違い、perl -i との比較、AIエージェントが実行した場合の危険性を紹介しています。
sed -i とは
sed -i(stream editor, in-place edit)は、テキストストリームを処理する sed コマンドに -i オプションを付けた形です。
通常の sed は処理結果を標準出力へ書き出しますが、-i を指定するとファイルを直接書き換えます。
設定ファイルや複数のソースファイルにわたって文字列を一括置換したい場合に特に有効で、シェルスクリプトやデプロイ自動化でも広く利用されています。
一方でファイルを直接上書きするため、誤ったパターンを指定するとデータが失われるリスクがある点に注意が必要です。
オプションの意味
| オプション | 意味 |
|---|---|
-i | ファイルをインプレース(直接)編集する。変更はファイルに即時反映される |
-i .bak | 編集前のファイルを指定した拡張子(例:.bak)でバックアップしてから編集する |
-i ''(macOS) | macOS の BSD sed でバックアップなしのインプレース編集を行う際に必要な空文字指定 |
-E(または -r) | 拡張正規表現(ERE)を有効にする。+、?、() などが使える |
s/旧/新/g | -i と組み合わせる置換コマンド。g フラグで行内すべてのマッチを置換する |
-i は単体では動作せず、必ず s///(置換)などの編集コマンドと組み合わせて使います。基本構文は sed -i 's/旧文字列/新文字列/g' ファイル名 です。
macOS と Linux の構文の違い
sed -i は macOS(BSD sed)と Linux(GNU sed)で構文が異なります。この違いはクロスプラットフォームなスクリプトを書く際の代表的な落とし穴です。
| 環境 | バックアップあり | バックアップなし |
|---|---|---|
| Linux(GNU sed) | sed -i.bak 's/old/new/g' file | sed -i 's/old/new/g' file |
| macOS(BSD sed) | sed -i .bak 's/old/new/g' file | sed -i '' 's/old/new/g' file |
macOS では -i の直後に拡張子または空文字 '' を引数として渡す必要があります。Linux の GNU sed では -i に続けて拡張子を붙ける形(スペースなし)か、バックアップなしの場合はオプションのみで動作します。両環境で動くスクリプトを書く場合は perl -i への切り替えも有効な選択肢です。
よく使う組み合わせ
文字列を一括置換する(基本)
# Linux: "localhost" を "example.com" に置換
sed -i 's/localhost/example.com/g' config.php
# macOS: 同じ操作
sed -i '' 's/localhost/example.com/g' config.php
最も基本的な使い方です。g フラグを付けることで、1行に複数マッチがある場合もすべて置換します。省くと各行の最初のマッチのみ置換されます。
バックアップを取りながら編集する
# Linux: .bak ファイルを残しつつ置換
sed -i.bak 's/debug=true/debug=false/g' app.conf
# 編集後に差分を確認
diff app.conf.bak app.conf
-i.bak のように拡張子を指定するとオリジナルファイルが app.conf.bak として保存されます。本番環境での編集前には必ずバックアップを取る習慣をつけましょう。
複数ファイルを一括編集する
# カレントディレクトリの全 .php ファイルを一括置換(Linux)
sed -i 's/old_function/new_function/g' *.php
# find と組み合わせてサブディレクトリ含め再帰的に処理
find . -name "*.php" -exec sed -i 's/old_function/new_function/g' {} ;
find と -exec を組み合わせることで、ディレクトリツリー全体にわたる一括置換が可能です。対象ファイルが多い場合は xargs を使う方が高速です:find . -name "*.php" | xargs sed -i 's/old/new/g'
特定行を削除する
# "# TODO" を含む行をファイルから削除(Linux)
sed -i '/# TODO/d' main.py
# 空行を削除
sed -i '/^$/d' config.ini
d(delete)コマンドと -i を組み合わせることで、パターンにマッチした行をファイルから直接削除できます。コメント行や空行の整理に便利です。
sed -i vs perl -i の違い
どちらもファイルのインプレース編集ができますが、移植性と正規表現の機能に差があります。
| 項目 | sed -i | perl -i |
|---|---|---|
| macOS/Linux 共通構文 | ×(構文が異なる) | ○(同一構文で動作) |
| 正規表現の種類 | BRE/ERE | PCRE(後読み・先読みなど使用可) |
| バックアップ指定 | -i.bak(Linux)/ -i .bak(macOS) | -i.bak(両環境共通) |
| 複数行処理 | △(追加設定が必要) | ○(-0777 フラグで容易) |
| 依存関係 | 標準インストール済み | Perl が必要(多くの環境で標準) |
macOS と Linux の両環境で動作するシェルスクリプトを書くなら perl -i -pe 's/old/new/g' file の構文が統一されており便利です。一方、sed -i は Perl 不要で軽量なため、Linux 専用スクリプトや簡単な置換には引き続き第一選択肢となります。
ユースケース
WordPress の wp-config.php を本番用に書き換える
# デバッグモードを無効化(Linux)
sed -i "s/define( 'WP_DEBUG', true )/define( 'WP_DEBUG', false )/" wp-config.php
# データベースホストを本番DBに変更
sed -i "s/define( 'DB_HOST', 'localhost' )/define( 'DB_HOST', 'db.example.com' )/" wp-config.php
デプロイスクリプトの中で設定ファイルを環境ごとに書き換える際に使います。CI/CD パイプラインに組み込むことで、手動編集によるミスを防げます。実行前に必ず -i.bak でバックアップを取るか、Git で差分を確認してから適用してください。
複数の設定ファイルにわたってIPアドレスを更新する
# /etc 以下の設定ファイル全体で旧IPを新IPに置換
find /etc -type f -name "*.conf" | xargs sed -i.bak 's/192\.168\.1\.100/192.168.1.200/g'
# バックアップファイルを一覧で確認
find /etc -name "*.conf.bak"
サーバー移行時にIPアドレスが変わった場合など、複数の設定ファイルを一括更新する用途に適しています。正規表現内の .(ドット)はメタ文字なのでバックスラッシュでエスケープする点に注意してください。
シェルスクリプトのテンプレート変数を展開する
# テンプレートファイルをコピーしてから変数を展開
cp template.conf output.conf
sed -i "s/{{APP_NAME}}/myapp/g" output.conf
sed -i "s/{{ENV}}/production/g" output.conf
sed -i "s/{{PORT}}/8080/g" output.conf
{{PLACEHOLDER}} 形式のテンプレートを実際の値に展開するパターンです。Docker の entrypoint スクリプトや Ansible の前処理としてもよく使われます。テンプレートのオリジナルは必ずコピーしてから編集し、元ファイルを保護してください。
AIエージェントとsed -i
目的、用途
AIエージェントは主に次のような目的で sed -i を実行しようとすることがあります。
- 設定ファイルの値(データベース接続先、デバッグフラグなど)を自動的に書き換えるために実行することがあります
- デプロイ処理の一環として、テンプレートファイル内のプレースホルダーを実際の値に置換するために実行することがあります
- ソースコード内の非推奨な関数名や変数名を新しい名称に一括リネームするために実行することがあります
危険性
sed -i コマンドは、ファイルを直接かつ即座に上書きする破壊的な操作を伴います。誤った正規表現や対象ファイルの指定ミスがあった場合、元のファイルの内容が失われても取り消すことができません。
また、 find と組み合わせると影響範囲が非常に広くなるため、AIエージェントが自動実行することは推奨されません。実行前に sed(-i なし)で置換後の内容を標準出力に確認し、問題がなければ -i.bak でバックアップ付きで実行するという手順を人間が確認した上で行うべきです。