正則表達(dá)式就像是一朵帶刺的玫瑰。它有著強(qiáng)大的字符串匹配能力,佐以 bash 命令(grep\sed 等)。能夠輸出賞心悅目的文本。但是它是帶刺的———不容易駕馭。要想達(dá)到隨心所欲,還需要勤加練習(xí)。
BRE 和 ERE
IEEE Std 1003.2(POSIX.2)給出了正則表達(dá)式(REs)的定義。定義中有兩種 REs :extended REs 和 basic REs。ERE 是 BRE 的擴(kuò)展?,F(xiàn)代的 REs 一般都是基于 ERE 的
基本概念
根據(jù) man re_format ,總結(jié)出一個(gè)容易記憶但不嚴(yán)謹(jǐn)的文法
RE --> branch
branch --> branch | piece
peice --> atom meta
meta --> * | + | ? | bound
bound --> {n, m}
atom --> (RE) | () | baracket expression | . | ^ | $ | \escape
escape --> ^
| .
| [
| $
| (
| )
| |
| *
| +
| ?
| {
| \
baracket --> [ a list of character]
來(lái)具體看看 grep 和 egrep 使用差異
先說(shuō)說(shuō)元字符。它指的是像 .、 *、 ?、 + 等有特殊含義的字符。
1、grep
-
a{1,2}匹配字串a{1,2} -
a\{1,2\}匹配字串a或aa
元字符需要 backslash(\) ,才能表示它在正則表達(dá)式中的特殊意義。grep 的語(yǔ)法屬于 BRE
2、egrep
-
a{1,2}匹配字串a或aa -
a\{1,2\}匹配字串a{1,2}
這里的 e 就是 Extened 的意思
元字符不需要 backslash(\) ,就能表示它在正則表達(dá)式中的特殊意義。egrep 的語(yǔ)法屬于 ERE
grep 和 egrep 的主要區(qū)別在于兩點(diǎn):
grep 元字符需要加上 backslash(\),egrep 不需要
-
元字符的數(shù)量不同
BRE(Unix grep),只包含
bracket expression[]、.、*、$、^EBR(Unix egrep),在支持 BRE 的基礎(chǔ)上,還增加了諸如
\w,\d等
幾個(gè)直觀的例子
1、匹配 hello 中的ll
-
grep
$ echo 'hello' | grep 'l\{2\}' --color -
egrep
$ echo 'hello' | egrep '1{2}' --color
2、使用組和反向引用來(lái)匹配連續(xù)重復(fù)兩次的字符。如,hellollooaa 中的 ll 、oo、aa
-
grep
$ echo 'hellollooaa' | grep '\([alo]\)\1' --color -
egrep
echo 'hellollooaa' | egrep '([alo])\1' --color
這里[]表達(dá)式就是 bracket expression。
() 表示匹配的組,\1 表示匹配到的第一組
這里的意思就是,匹配第一組兩次。所以只匹配 aa 、ll、oo
**egrep 和 grep ** 不支持在 [] 使用用 \w 等縮寫
bash 對(duì)命令參數(shù)預(yù)先轉(zhuǎn)義
bash 在執(zhí)行 echo 前,會(huì)對(duì) echo 的參數(shù)先轉(zhuǎn)義。轉(zhuǎn)義的后的參數(shù),再傳給 echo
$ echo \\
\
$ echo "\\"
\
$ echo '\\'
\\
bash 默認(rèn)是會(huì)對(duì)參數(shù)轉(zhuǎn)義的
將參數(shù)包裹在 ''中,就能避免參數(shù)被 bash 轉(zhuǎn)義
來(lái)看一個(gè)有趣的例子
我們 grep 一下 echo 的輸出

一開始看到這個(gè)結(jié)果(匹配部分是紅色),我的內(nèi)心是懵逼的
但是,套用我們前面的解釋。
可以很清晰地得到結(jié)果
-
\\.由 bash 解釋為\.傳遞給 grep ,grep 再將\.解釋為.,就匹配了
.... \.由 bash 解釋為.傳遞給 grep,grep 自然就匹配了全串
其他結(jié)果也可輕易得出,不再贅述