Linuxのコマンドで使われる正規表現の違い
2020/02/21更新
目次
概要
PerlやJavaScriptの正規表現に慣れていると、+
などのメタ文字そのものを表記する場合に\+
とエスケープするのは当然であるが、sedやgrepなどのLinuxコマンドで正規表現を使うと、これが逆になっており、+
で文字そのもの、\+
でメタ文字となることがある。実はこれは、POSIXで標準化されている基本正規表現(BRE:Basic Regular Expression)と拡張正規表現(ERE:Extended Regular Expression)の違いによるものである。どのようなときにその違いが出るのか、他にはどのような違いがあるのか、調べたのでここにまとめておく。
基本正規表現(BRE)と拡張正規表現(ERE)の違い
BREとEREの主な違いは以下の表の通りである。BREでは、黄色く示した部分で、通常文字とメタ文字のどちらをエスケープするかがEREと逆になっている。また、※で示した3つ(\+
、\?
、\|
)は本来BREのものではなく、GNUの拡張によってgrepやsedなどのコマンドが追加で実装しているものである。
基本正規表現(BRE) | 拡張正規表現(ERE) | |
---|---|---|
先頭 |
|
|
末尾 |
|
|
任意の1文字 |
|
|
いずれか1文字 |
|
|
いずれでもない1文字 |
|
|
0回以上 |
|
|
1回以上 |
|
|
0回または1回 |
|
|
n回 |
|
|
n回以上m回以下 |
|
|
グループ |
|
|
または |
|
|
BREでは、いくつかのメタ文字にエスケープが必要となるため、EREに慣れていると不便に感じるが、逆にこれらの文字を多く使う場合は、通常文字としてのエスケープの必要が無くなるので、むしろBREの方が適していると考えることもできる。
エスケープが必要な文字 | |
---|---|
基本正規表現(BRE) |
|
拡張正規表現(ERE) |
|
なお、PerlやJavaScriptなどのプログラミング言語で使われる正規表現は、EREをさらに拡張したものである。
grepやsedでの使い分け
grepやsedコマンドに渡した正規表現は、標準ではBREと認識されるが、-E
などのオプションを使うことでEREを使うことができる。
例えば、以下のような内容のa.txt
があったとする。
aaaaa a{5}
このテキストファイルに対してBREとEREでgrepすると以下のようになる。
# 標準ではBREとして解釈される。 grep 'a{5}' a.txt # a{5} grep 'a\{5\}' a.txt # aaaaa grep 'aa\+' a.txt # aaaaa(\+はGNUによる拡張) # -EオプションによってEREを使用できる。 grep -E 'a{5}' a.txt # aaaaa grep -E 'a\{5\}' a.txt # a{5} grep -E 'aa+' a.txt # aaaaa
Bashのif [[~]]で使える正規表現
Bashでif [[ $hoge =~ pattern ]]
という構文があるが、このときに使える正規表現はEREである。なお、[[~]]
の中では、正規表現を/~/
や"~"
などと囲わずにそのまま書くというのが注意点である。
str="aaaaa" if [[ $str =~ a{5} ]] then echo "OK." fi