🐧 Linux 総合学習プラットフォーム
正規表現・テキスト処理 ・ 中級

拡張正規表現(grep -E / egrep)

正規表現には基本(BRE)と拡張(ERE)の2つの方言があります。基本では + ? { } ( ) | を使うのに \ が必要ですが、grep -E(旧来は egrep)を使う拡張ではこれらをそのまま書けて読みやすくなります。例えば基本の grep "ab\+" は拡張では grep -E "ab+" と書けます。さらに ( ) でグループ化し、| で「または」を表せるので、grep -E "cat|dog" のように複数の語をまとめて検索できます。今のegrepは grep -E の別名で、新しく書くなら -E が推奨です。

正規表現には、見た目はよく似ているのに細部の扱いが違う「方言」があります。代表的なのが、grep や sed が標準で使う基本正規表現(BRE)と、grep -E で使う拡張正規表現(ERE)の2つです。両者の最大の違いは、+ ? | ( ) { } といった一部の記号について、バックスラッシュ \ の要否が逆になることです。この違いを理解すると、複雑なパターンを格段に読みやすく書けるようになり、grep の表現力がひと回り広がります。歴史的には拡張側を egrep という別コマンドが担っていましたが、今は grep -E に一本化されています。どちらの方言を選んでも表現できることの範囲はほぼ同じで、違うのはあくまで「書き方の手間」です。

BRE と ERE で何が違うのか

BRE では、+ ? | ( ) { } を特別な意味で使うには、直前に \ を付けて \+ \? \| \( \) \{ \} と書く必要があります。これに対して ERE では、これらをエスケープなしでそのまま書けます。たとえば「a が1回以上」を表すとき、BRE では grep 'a\+'、ERE では grep -E 'a+' と書きます。同じく「数字がちょうど4個」は BRE が grep '[0-9]\{4\}'、ERE が grep -E '[0-9]{4}' です。覚え方はシンプルで、「ERE はそのまま書ける、BRE はバックスラッシュを足す」。エスケープの向きがちょうど逆になっている、と捉えるとよいでしょう。逆に言えば、式が \( や \| だらけで読みにくくなってきたら、-E を付けて ERE に切り替えると一気に見通しがよくなります。なお . * ^ $ [ ] の基本記号はどちらの方言でも同じ意味なので、そこは共通の土台として安心して使えます。

グループ化と選択が書きやすくなる

ERE の便利さがとくに際立つのが、( ) によるグループ化と | による選択(または)です。| は「左右のどちらか」を表し、grep -E 'cat|dog' なら cat か dog を含む行に一致します。複数の語をまとめて探せるので、grep -E 'error|warning|fail' app.log のようにログの重要語を一度に拾う使い方が定番で、末尾に | wc -l を足せば該当件数も数えられます。( ) でくくると、量指定子をまとまり全体に効かせられます。たとえば grep -E '(ab)+' は ab のくり返し(ab, abab, ababab…)に一致します。同じことを BRE で書くと grep '\(ab\)\+' となり、記号が増えて読みにくくなるのが分かります。複数候補やグループを扱いたくなったら ERE、と覚えておくと自然に手が動きます。

egrep ではなく grep -E を

歴史的には、拡張正規表現を使う専用コマンドとして egrep が、正規表現として解釈しない固定文字列検索の専用コマンドとして fgrep がありました。現在の egrep は中身が grep -E を、fgrep は grep -F を呼ぶだけのラッパで、新しい GNU grep で egrep を使うと「egrep is obsolescent; using grep -E」という非推奨の警告が出ます。これから書くものは grep -E に統一しておくのが安全です。あわせて grep -F も覚えておくと便利で、これは . や * を含む文字列を正規表現として解釈せずそのまま探すので、IPアドレスやバージョン番号のようにメタ文字を含む固定文字列を、エスケープを気にせず検索できます。

よくある失敗

つまずきやすいのは、-E を付け忘れたまま ERE の書き方をしてしまうケースです。grep 'cat|dog' と書くと、BRE では | がただの文字になり、「cat|dog という文字列そのもの」を探してしまって意図どおりに一致しません。BRE のまま「または」を使いたいなら grep 'cat\|dog' と \| にする必要があります。同じく grep 'a{2,4}' は BRE では波かっこが文字扱いになって効かないので、grep -E 'a{2,4}' とするか grep 'a\{2,4\}' と書きます。逆方向の失敗もあり、ERE のつもりで grep -E 'a\+' と余計なエスケープをすると、環境によっては \+ が「文字としての +」と解釈され、素の a+ とは挙動が変わってしまいます。ERE では必要なとき以外は \ を付けない、というのも一つの原則です。「いま自分はどちらの方言で書いているのか」を常に意識するのが、この種の混乱を避ける最大のこつです。

実務の使いどころ

実務では、単純な語の検索は BRE のまま素早く、複数候補をまとめたい・グループ化したい・回数を指定したいときは -E を付けて ERE で、と使い分けるのが自然です。sed でも grep でも基本は BRE なので、凝ったパターンが必要になった瞬間に -E(sed なら -E や -r)へ切り替える、という判断を身につけると作業が滑らかになります。たとえば複数の単語を一度に置換したいとき、sed -E 's/(cat|dog)/pet/g' のように ERE を有効にすると \( や \| を書かずに済み、式がぐっと読みやすくなります。同じパターンを grep でも sed でも使い回せるのも、ERE に揃える利点です。なお GNU grep には -P という第三のモード(PCRE)もあり、\d(数字)や \b(単語境界)といった強力な短縮表記が使えますが、環境によって無効化されていることがあり移植性は -E に劣ります。「手元で素早く凝ったことをしたいなら -P、どこでも確実に動かしたいなら -E」と棲み分けると、状況に応じて最短手を選べます。

この項目に出てくる用語

拡張正規表現(ERE)かくちょうせいきひょうげん
grep -E などで使う方言。+ ? { } ( ) | をそのまま書ける。
基本正規表現(BRE)きほんせいきひょうげん
grep や sed の既定方言。+ ? { } ( ) | に \ が必要。

関連コマンド

grepegrep

▶ 学習アプリでこの続きを学ぶ・演習する