这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文本命令技巧(下)
字符编码解惑