這grep咋還不支援\d呢(BRE,ERE,PCRE)
原創:打碼日記(微信公眾號ID:codelogs),歡迎分享,轉載請保留出處。
簡介
對於剛使用Linux不久的同學,肯定會遇到這個問題,就是用grep匹配數字時,發現\d
匹配不了數字。
主要原因是grep支援三種正則表示式BRE
,ERE
,PCRE
,而其預設使用的是BRE
,但\d
是定義在PCRE
中的,所以grep預設是不支援\d
的。
正則表示式分類
BRE
基本的正則表示式(Basic Regular Expression 簡稱 BRE),由posix標準定義,為了統一歷史上混亂的正則實現。
ERE
擴充套件的正則表示式(Extended Regular Expression 簡稱 ERE),由posix標準定義,解決了一些BRE的缺陷並補充了一些新功能。
PCRE
Perl相容的正則表示式(Perl Compatible Regular Expression 簡稱 PCRE),由perl語言發展而來,而後移植到各平臺與程式語言中,所以稱其為Perl相容的正則表示式。
如今主流程式語言(java,python)中的正則實現,基本都是PCRE,PCRE功能也比BRE,ERE要強大得多,雖然大部分同學只知道其基礎部分。
BRE,ERE,PCRE對比
功能 | 描述 | BRE | ERE | PCRE |
---|---|---|---|---|
字元組 | 匹配指定任一字元 | [..] |
[..] |
[..] |
排除字元組 | 匹配非指定任一字元 | [^..] |
[^..] |
[^..] |
簡寫字元組.號 | 匹配非換行字元 | . |
. |
. |
簡寫字元組 | 匹配數字 匹配非數字 |
不支援 | 不支援 |
\d \D
|
簡寫字元組 | 匹配字母資料下劃線 匹配非字母數字下劃線 |
\w \W
|
\w \W
|
\w \W
|
簡寫字元組 | 匹配空白符 匹配非空白符 |
\s \S
|
\s \S
|
\s \S
|
匹配量詞 | 匹配0次或多次 | * |
* |
* |
匹配量詞 | 匹配1次或多次 | \+ |
+ |
+ |
匹配量詞 | 匹配0次或1次 | \? |
? |
? |
匹配量詞 | 匹配x次 匹配x次或以上 匹配x次或以上y次或以下 |
\{x\} \{x,\} \{x,y\}
|
{x} {x,} {x,y}
|
{x} {x,} {x,y}
|
懶惰匹配量詞 | 儘量不匹配 | 不支援 | 不支援 |
*? +? ?? {x}? {x,}? {x,y}?
|
佔有匹配量詞 | 匹配後就不會回溯 | 不支援 | 不支援 |
*+ ++ ?+ {x}+ {x,}+ {x,y}+
|
位置限定 | 匹配行開頭位置 | ^ |
^ |
^ |
位置限定 | 匹配行結尾位置 | $ |
$ |
$ |
位置限定 | 匹配單詞邊界 匹配非單詞邊界 |
\b \B
|
\b \B
|
\b \B
|
多選結構 | 多選匹配條件 | | |
` | ` |
捕獲組與反向引用 | 分組並捕獲 |
\(...\) \1 \2
|
(...) \1 \2
|
(...) \1 \2
|
僅分組 | 僅分組不捕獲括號 | 不支援 | 不支援 | (?:) |
固化分組 | 匹配後就不回溯的分組 | 不支援 | 不支援 | (?>) |
環視 | 零長度斷言 | 不支援 | 不支援 |
(?=...) (?!...) (?<=...) (?<!...)
|
可以發現BRE與ERE的主要區別是,BRE對於+
,?
,{x}
,|
,()
,需要使用\
轉義後,才能表達正則的含義,否則視為普通字元,而ERE預設表示正則元字元,加\
才是普通字元。
另外,對於我們常用的\d
,BRE與ERE都不支援。
命令與它們的正則分類
grep
對於grep,預設使用BRE,grep -E
或egrep
使用ERE,實際上grep -E
與egrep
是等價的,grep -P
使用PCRE。
另外,值得一提的是grep -F
代表普通字串匹配,grep -w
代表單詞模式匹配,如grep -w abc
等價於grep '\babc\b'
,其中\b
用於匹配單詞邊界。
sed
對於sed,預設也使用BRE,sed -E
或sed -r
使用ERE,sed不支援PCRE。
awk
對於awk來說,預設就是ERE,它不支援BRE與PCRE。
另外,PCRE釋出了兩個新的輪子pcregrep
與pcre2grep
,功能上類似於grep,不過是專門用PCRE規範實現的,pcre2grep
有個好用的功能,可以很方便的使用正則提取資料,如下:
$ echo -e 'name:zhangsan,age:18 \n name:lisi,age:20' | pcre2grep -O '$1 $2' 'name:(\w+),age:(\d+)'
zhangsan 18
lisi 20
往期內容
不容易自己琢磨出來的正則表示式用法
原來awk真是神器啊
Linux文字命令技巧(上)
Linux文字命令技巧(下)
字元編碼解惑