クリップボードにコピーしました!
文字列のsed

sedと正規表現の基本から応用まで――文字列処理を自在に操る

updated: 2026/04/16 created: 2026/04/16

はじめに

コマンドラインで文字列を操作するとき、sedは非常に強力な選択肢です。ファイルの内容を置換したり、特定の行を抽出したりと、正規表現と組み合わせることで複雑な処理も1行で完結します。

本記事では、sedの基本的な使い方から、正規表現を活用した応用的なテクニックまでを順を追って解説します。初学者が躓きやすいポイントにも触れながら進めていくので、コマンドに慣れていない方でも読み進められる構成になっています。

参考:sed, a stream editor - GNU公式ドキュメント

sedと正規表現で最初の1文字をHに置き換える仕組み

今回メインで扱うコマンドは以下です。

sed 's/./H/' input.txt
要素内容
sedストリームエディタ。ファイルや標準入力を1行ずつ処理する
's/./H/'置換コマンド。s/検索パターン/置換文字列/ の形式
.正規表現の任意の1文字にマッチするメタ文字
H置換後の文字列
input.txt処理対象のファイル

フラグなしのsコマンドは、各行の最初にマッチした箇所だけを置換します。そのため、各行の先頭の1文字だけがHに変わります。

実行前の状態

まず、以下のコマンドでinput.txtを作成します。タブ文字を含む行があるため、ターミナルでタブを入力する際はCtrl+vを押した後にTabキーを押す必要があります。

cat << 'EOF' > input.txt
hello.
world.

hello world.
	hello.
1hello 2world.
EOF

input.txt の内容:

hello.
world.

hello world.
	hello.
1hello 2world.

実行後の状態

sed 's/./H/' input.txt

出力結果:

Hello.
Horld.

Hello world.
Hhello.
Hhello 2world.

空行はマッチする文字がないため変化しません。5行目はタブ文字が先頭にあるため、タブがHに置き換わります。6行目は1が最初の1文字なので1Hになります。

実行画像

GNU sedとBSD sedの挙動の違い

macOSに標準搭載されているのはBSD版のsed、LinuxにはGNU版のsedが搭載されていることが多いです。同じコマンドでも挙動が異なる場合があります。

項目GNU sedBSD sed
-iオプション(インプレース編集)sed -i 's/a/b/' filesed -i '' 's/a/b/' file(バックアップ拡張子が必要)
\t(タブ)正規表現内で使用可能使用できない場合がある
\+\?BREで使用可能使用できない
-Eオプション拡張正規表現を有効化同様に使用可能

本記事では断りのない限りBSD版のsedでコマンドを記述します。

helloをHIに全置換する

sed 's/hello/HI/g' input.txt
要素内容
s置換コマンド
hello検索する文字列
HI置換後の文字列
gグローバルフラグ。行内のすべてのマッチを置換する

フラグなしだと各行で最初の1件だけ置換されます。gをつけることで、1行に複数のマッチがあっても全件置換されます。6行目のhelloも置換対象になります。

helloを含む行だけを抽出する

sed -n '/hello/p' input.txt
要素内容
-nデフォルトの出力を抑制する
/hello/マッチするパターン
pマッチした行を出力する

sedはデフォルトで全行を出力します。-nで出力を抑制し、pコマンドで明示的にマッチした行だけを表示することで、grepのような抽出処理が実現できます。

後方参照を使った列の抽出

sed -n 's/\(hello\).*/\1/p' input.txt
要素内容
\(hello\)グループ化。マッチした内容を\1として参照できる
.*任意の文字列(0文字以上)
\11つ目のグループに一致した文字列を参照する
p置換が成功した行のみ出力

正規表現のグループ化と後方参照を使うことで、行の一部分だけを切り出す列の抽出が可能です。

後方参照でhelloとworldの順番を入れ替える

sed -n 's/\(hello\) \(world\)/\2 \1/p' input.txt
要素内容
\(hello\)1つ目のグループ(\1で参照)
\(world\)2つ目のグループ(\2で参照)
\2 \1グループの順序を入れ替えて出力

後方参照はグループ番号の順に\1\2と増えていきます。「hello world」とマッチする行で置換が行われ、world helloとして出力されます。

連続した改行を取り除く

sed 'N;s/^\n//' input.txt
要素内容
N次の行をパターンスペースに読み込んで連結する
s/^\n//先頭の改行文字を削除する

sedは通常1行ずつ処理します。Nコマンドを使うことで次の行も読み込み、2行分をまとめて処理できます。空行を含む連続した改行を除去する場合、Nがないとパターンスペースに改行が含まれないためマッチしません。

スペースをアンダースコアに置き換える

sed 's/ /_/g' input.txt
要素内容
半角スペース
_置換後の文字列
g行内の全マッチを置換

単純な見た目ですが、全角スペースとの混同が原因でマッチしないケースがよくある失敗例です。正規表現でのスペース処理は文字の種類に注意が必要です。

タブ文字をSPACEという文字列に置き換える

sed 's/\t/SPACE/g' input.txt
要素内容
\tタブ文字を表すエスケープシーケンス
SPACE置換後の文字列

BSD版のsedでは\tが使えない場合があります。その際はCtrl+v → Tabで実際のタブ文字を埋め込む方法があります。input.txtの5行目にはタブが含まれているため、このコマンドで確認できます。

ドット(.)をエスケープしてDOTに置換する

sed 's/\./DOT/g' input.txt
要素内容
\.エスケープされたドット。文字としての.にマッチ
DOT置換後の文字列

正規表現において.は「任意の1文字」を意味するメタ文字です。文字としてのドットにマッチさせるには\.とエスケープする必要があります。エスケープを忘れると、すべての文字がマッチして意図しない置換が起こります。

数字を#に置き換える

sed 's/[0-9]/#/g' input.txt
要素内容
[0-9]0から9の任意の1文字にマッチする文字クラス
#置換後の文字列

[0-9]は正規表現の文字クラスで、数字1文字を表します。\dはBSD版のsedでは使えないため、[0-9]を使うのが確実です。

シェル変数・$1を活用した動的な置換

sedのコマンドをダブルクォートで囲むと、シェル変数を展開できます。

var="argument"
sed "s/hello/$var/" input.txt
sed 's/hello/$var/' input.txt
要素内容
"s/hello/$var/"ダブルクォート。シェルが$varを展開してargumentになる
's/hello/$var/'シングルクォート。$varがそのまま文字列として扱われる

シングルクォートでは変数は展開されません。シェルスクリプトでは$1(第1引数)を使うことがよくあります。例えばsed "s/hello/$1/" input.txtとすれば、スクリプト実行時に渡した引数で置換文字列を変えることができます。

最長一致と最短一致の違い

sed -E 's/h.*o/X/' input.txt
要素内容
h.*ohで始まりoで終わる、できるだけ長い文字列にマッチ(最長一致)

sedの.*はデフォルトで最長一致(greedy)です。hello worldに対してh.*ohelloではなくhello woの最後のoまで含むより長い部分にマッチします。

最短一致はBSD版のsedではサポートされていません。GNU sedでも\{0,\}のような迂回策が必要です。最短一致が必要な場合はPerlやPythonの利用を検討してください。

特定の行だけを対象にした置換

sed '4s/hello/HI/' input.txt
要素内容
44行目だけを処理対象にするアドレス指定
s/hello/HI/置換コマンド

アドレス指定を使うと、特定の行番号や正規表現にマッチする行だけに処理を限定できます。2,4s/hello/HI/のように範囲指定も可能です。

BREとEREについて

sedの正規表現にはBRE(基本正規表現)とERE(拡張正規表現)の2種類があります。

BREの例:

sed 's/\(hello\)/HI/' input.txt

BREではグループ化に\(\)を使います。

EREの例:

sed -E 's/(hello)/HI/' input.txt

-Eオプションを付けるとEREが有効になり、()だけでグループ化できます。BREでは\(が必要な箇所も、EREでは省略できるためコマンドがシンプルになります。

拡張正規表現でhelloまたはworldをXに置換する

sed -E 's/(hello|world)/X/g' input.txt
要素内容
-E拡張正規表現を有効化
(hello|world)helloまたはworldにマッチ
X置換後の文字列

EREでは|のままで動作します。

sedでよく使う正規表現の一覧

.任意の1文字s/./X/
*直前の文字の0回以上の繰り返しs/el*/X/
^行頭s/^/> /
$行末s/$/ end/
[abc]a、b、cのいずれか1文字s/[abc]/*/g
[^abc]a、b、c以外の1文字s/[^abc]//g
[0-9]数字1文字s/[0-9]/#/g
\(…\)グループ化(BRE)s/\(hello\)/[\1]/
\1後方参照s/\(hello\) \(world\)/\2\1/
\.文字としてのドットs/\./,/g
\tタブ文字(GNU sed)s/\t/ /g
+1回以上(ERE)s/[0-9]+/#/g
?0または1回(ERE)s/e?l/X/g
|または(ERE)s/hello|world/X/g

逆引き:やりたいことからコマンドを探す

例1:行頭に文字列を追加する

cat << 'EOF' > input.txt
hello.
world.
EOF
sed 's/^/> /' input.txt

^で行頭にマッチし、> を挿入します。

例2:行末の不要なスペースを削除する

cat << 'EOF' > input.txt
hello   
world   
EOF
sed 's/ *$//' input.txt

$で行末にマッチし、その手前のスペースを削除します。

例3:空行を削除する

cat << 'EOF' > input.txt
hello.

world.
EOF
sed '/^$/d' input.txt

^$は行頭と行末が直接続く、つまり空行にマッチします。dコマンドでその行を削除します。

うまく動かないときに見直したいコマンドの落とし穴

全角スペースの削除で何も変わらない

cat << 'EOF' > sample.txt
hello world
EOF
sed 's/ //g' sample.txt

このコマンドは全角スペースを削除するように見えますが、ターミナルの文字コードやコピペの際に半角スペースに変換されていると、マッチせず何も変わりません。ファイルに実際に全角スペースが入っているかcat -Aなどで確認してください。

HTMLタグの除去で行全体が消える

cat << 'EOF' > sample.txt
<p>hello</p> and <span>world</span>
EOF
sed 's/<.*>//g' sample.txt

.*は最長一致のため、<p>から最後の</span>まで行全体がマッチして消えてしまいます。HTMLタグの除去には[^>]*を使うことで最初の>までに限定できます。

日付フォーマット変換でバックスラッシュエラーが起きる

cat << 'EOF' > sample.txt
2024-04-16
EOF
sed 's/\([0-9]\+\)-\([0-9]\+\)-\([0-9]\+\)/\3\/\2\/\1/' sample.txt

BSD版のsedでは\+(1回以上の繰り返し)がサポートされていない場合があります。この場合は[0-9][0-9]*のように書き換えるか、-Eオプションで拡張正規表現に切り替えてください。

sedと正規表現を使いこなして文字列処理の幅を広げる

sedは一見シンプルなコマンドですが、正規表現と組み合わせることで置換・抽出・整形など幅広い処理に対応できます。初学者のうちはBREとEREの違いや、BSD版とGNU版の挙動の差に戸惑うことがありますが、本記事で紹介したコマンドを実際に動かしながら確認することで理解が深まります。まずは小さなファイルで試し、少しずつ応用範囲を広げていきましょう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

©︎ 2025-2026 running terminal commands