sed で正規表現が効かない/一致しないときのチェックポイント

  • URLをコピーしました!
目次

はじめに

Linuxで sed を使ってテキストを置換するとき、正規表現が効かない/一致しない というトラブルはよくあります。

例:

$ echo "hello123" | sed 's/[0-9]+/NUM/'
helloNUM3   # ← 期待した結果と違う

「正規表現の書き方は合っているのに、なぜ一致しないのか?」
その原因は多くの場合、sedの正規表現仕様の違いエスケープ不足 にあります。

1. sed の正規表現モード

基本正規表現(BRE: Basic Regular Expression)

  • sed がデフォルトで使うモード
  • +? などのメタ文字は使えない
  • \+ のようにバックスラッシュでエスケープする必要あり

例(数字の1回以上の繰り返しにマッチさせたい場合):

echo "hello123" | sed 's/[0-9]\+/NUM/'
# 出力: helloNUM

拡張正規表現(ERE: Extended Regular Expression)

  • +? がそのまま使える
  • sed -E または sed -r(GNU sed) を指定すると利用可能

例:

echo "hello123" | sed -E 's/[0-9]+/NUM/'
# 出力: helloNUM

👉 原因あるある
「Perlやgrepの感覚で + をそのまま書いても、sedではBREがデフォルトなので効かない」という落とし穴。

2. よくある「一致しない」パターンと解決策

パターン1:+? が効かない

  • 原因 → BREでは特殊文字として認識されない
  • 対策 → \+ にするか、-E オプションを使う

パターン2:括弧のグループ化

echo "abc123" | sed 's/\([0-9]\+\)/NUM/'
  • BREでは () はリテラル扱い → \(\) にする必要あり
  • EREでは () をそのまま使える
echo "abc123" | sed -E 's/([0-9]+)/NUM/'

パターン3:波かっこ {n,m} が効かない

  • BREでは \{n,m\} のようにバックスラッシュが必要
  • EREではそのまま {n,m} が使える
echo "aaaa" | sed 's/a\{2,3\}/X/'   # BRE
echo "aaaa" | sed -E 's/a{2,3}/X/'  # ERE

3. エスケープ処理の注意点

  • \ がシェルで解釈されるケースに注意(特にbash/zsh)
  • シングルクォート ' ' で囲むと安全

例(NG例):

sed "s/\([0-9]\+\)/NUM/"
# → シェルが `\(` を解釈してしまい、意図通りに動かない

例(OK例):

sed 's/\([0-9]\+\)/NUM/'

4. 実務でのチェックポイント

  1. BREかEREかを意識する
    → デフォルトはBRE、迷ったら -E を付ける
  2. バックスラッシュを正しく使う
    → BREでは \+\?\{n,m\}\( が必須
  3. シェルでのエスケープを考慮する
    → 基本はシングルクォートで囲む

まとめ

  • sed はデフォルトで 基本正規表現(BRE) を使う
  • +?{n,m} などが効かないときは → -E を使うか、バックスラッシュを追加
  • グループ化 () も同様にエスケープが必要(BREの場合)
  • シェルの解釈と競合しないよう、シングルクォートで囲むのが安全

👉 「sedで正規表現が効かない」と感じたら、まず BRE/EREの違い をチェックすることが解決の第一歩です。

よくあるエラーと解決方法まとめ
目次