sed
| 対応: | Bash 1.0(1989) |
|---|
『sed』(Stream EDitor)はテキストを行単位で処理するコマンドです。置換・削除・挿入・抽出などの編集をファイルを開かずに行えます。スクリプトや自動化処理でよく使われます。
構文
sed [オプション] 'コマンド' [ファイル...]
sed [オプション] -e 'コマンド1' -e 'コマンド2' [ファイル...]
コマンド・オプション一覧
| コマンド / オプション | 概要 |
|---|---|
| s/置換前/置換後/ | 各行の最初にマッチした部分を置換します。 |
| s/置換前/置換後/g | 各行のすべてにマッチした部分を置換します(グローバル)。 |
| s/置換前/置換後/i | 大文字小文字を区別せずに置換します。 |
| -i ファイル | ファイルをインプレース(直接)編集します。 |
| -i.bak ファイル | バックアップを .bak に保存してからインプレース編集します。 |
| -n | デフォルトの出力を抑制します(p コマンドと組み合わせて使います)。 |
| /パターン/d | パターンに一致する行を削除します。 |
| /パターン/p | パターンに一致する行を出力します(-n と組み合わせて使います)。 |
| Nd | N行目を削除します。 |
| N,Md | N行目からM行目を削除します。 |
| /パターン/a テキスト | 一致する行の後にテキストを追加します。 |
| /パターン/i テキスト | 一致する行の前にテキストを挿入します。 |
サンプルコード
以下のファイルを例に説明します。
data.txt
Hello World foo foo This is a foo test Another line here
config.txt
# Database settings host=localhost # Port number port=3306
『s/置換前/置換後/』で最初にマッチした部分を置換します。『g』を付けるとすべて置換します。
sed 's/foo/bar/' data.txt Hello World bar foo This is a bar test Another line here
sed 's/foo/bar/g' data.txt Hello World bar bar This is a bar test Another line here
『/パターン/d』でパターンに一致する行を削除します。コメント行(# で始まる行)を除外する例です。
sed '/^#/d' config.txt host=localhost port=3306
『/^$/d』で空行を削除します。
printf "line1\n\nline2\n\nline3\n" | sed '/^$/d' line1 line2 line3
『-n』と『p』コマンドの組み合わせで、特定の行のみを抽出します。
sed -n '2,4p' config.txt host=localhost # Port number port=3306
『-e』で複数の置換を一度に実行します。
sed -e 's/foo/bar/g' -e 's/World/Earth/' data.txt Hello Earth bar bar This is a bar test Another line here
『-i』でファイルを直接編集します(インプレース置換)。『-i.bak』でバックアップを作成してから編集します。
sed -i 's/old/new/g' file.txt
sed -i.bak 's/old/new/g' file.txt
先頭と末尾の空白を削除します(トリム)。
echo " hello world " | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' hello world
1行目を削除します(CSVのヘッダーを除く場合などに使います)。
echo -e "name,age\n桐生一馬,37\n真島吾朗,39" | sed '1d' 桐生一馬,37 真島吾朗,39
正規表現との組み合わせ
sed は POSIX 拡張正規表現をサポートします(GNU sed では『-E』オプションを付けると ERE が使えます)。
数字だけの行を削除します(BRE)。
printf "abc\n123\nfoo456\n789\n" | sed '/^[0-9]*$/d' abc foo456
『-E』で拡張正規表現(ERE)を使います。『+』や『?』がバックスラッシュ不要になります。
printf "color\ncolour\n" | sed -E 's/colou?r/hue/g' hue hue
キャプチャグループ(\1)で一部を保持しながら置換します。『YYYY-MM-DD』を『DD/MM/YYYY』形式に変換します。
echo "2025-03-28" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
28/03/2025
BSD sed(macOS)と GNU sed(Linux)の違い
macOS に標準搭載されている sed は BSD sed、Linux に標準搭載されている sed は GNU sed です。オプションや正規表現の書き方に違いがあり、片方で動くスクリプトがもう片方でエラーになることがよくあります。ローカルが macOS、CI/CD やサーバーが Linux という環境では特に注意が必要です。
| 機能 | GNU sed(Linux) | BSD sed(macOS) |
|---|---|---|
| バックアップなしで直接編集 | sed -i 's/a/b/g' file | sed -i '' 's/a/b/g' file(空文字が必須) |
| バックアップを作成して編集 | sed -i.bak 's/a/b/g' file | sed -i.bak 's/a/b/g' file(共通) |
| 拡張正規表現 | -r または -E | -E のみ(-r は使えない) |
| \n で改行を挿入 | sed 's/a/b\n/g'(そのまま使える) | リテラルの改行が必要($'\n' 等) |
| \t でタブを挿入 | sed 's/a/\t/g'(そのまま使える) | リテラルのタブが必要($'\t' 等) |
| 大文字小文字を無視して置換 | sed 's/foo/bar/Ig'(I フラグ) | 非対応 |
バックアップ拡張子を付ける方法は両環境で共通です。
sed -i.bak 's/localhost/127.0.0.1/g' config.txt
config.txt が書き換えられ、config.txt.bak に元のファイルが残ります。
拡張正規表現を使う場合は『-E』に統一しておくと両環境で動きます(GNU sed も『-E』に対応しています)。
sed -E 's/colou?r/hue/g' data.txt hue hue
改行・タブの挿入は両環境で書き方が違うため、printf や $'\n' を使って回避するのが確実です。
sed "s/:/$(printf '\n')/g" data.txt
macOS 上で GNU sed を使いたい場合は Homebrew でインストールできます。インストール後は『gsed』コマンドで使えます。
brew install gnu-sed gsed -i 's/old/new/g' file.txt
スクリプト内で環境を判定して切り替える方法もあります。
if sed --version > /dev/null 2>&1; then
SED="sed"
else
SED="gsed"
fi
$SED -i 's/old/new/g' file.txt
GNU sed には『--version』オプションがありますが、BSD sed にはありません。この違いを利用して環境を判定できます。
よくあるミス1: 区切り文字のスラッシュ
区切り文字にスラッシュを使うとパスの置換が書きにくく、シンタックスエラーの原因になります。区切り文字は『/』以外にも『|』『@』『#』など任意の文字が使えるので、置換対象にスラッシュが含まれる場合は別の文字が有効です。
sed 's|/var/log|/var/www|g' file.txt
よくあるミス2: -nなしでpを使う
『-n』なしで『p』を使うと、各行が通常出力に加えて『p』でも出力されるため2倍になります。特定の行だけ抽出したい場合は『-n』と『p』をセットで使うのが定石です。
sed 'p' data.txt Hello World foo foo Hello World foo foo This is a foo test This is a foo test Another line here Another line here
sed -n 'p' data.txt Hello World foo foo This is a foo test Another line here
sed -n '2,4p' data.txt This is a foo test Another line here
概要
『$ sed -i』でインプレース編集するときは必ずバックアップを取るか、git 管理下で行うと安全です。macOS の場合は BSD sed を使用しているため、GNU sed と一部オプションの書き方が異なります(例:macOS では『$ sed -i ""』と空文字が必要)。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。