关于grep正则表达式选项(ERE、BRE、Perl regex)差异的咨询
搞定grep的三种正则风格:BRE、ERE、Perl正则
嘿,我太懂这种抓耳挠腮的感觉了——grep的三种正则风格差异真的是新手入门的重灾区,尤其是刚摸清楚基础正则,转头就被BRE/ERE/PCRE的规则搞混!我当初也因为误用*踩过好多次坑,下面给你掰扯清楚这三者的核心差异,还有你关心的*问题。
1. 基础正则表达式(BRE):grep默认款,最“古板”的风格
这是grep不带任何参数时默认用的正则,特点是大部分特殊元字符必须转义才能生效,不然会被当成普通字符:
- 比如你想匹配一个或多个
a,不能直接写a+,得写成a\+;想分组或者用“或”逻辑,()和|都要加反斜杠变成\(\)和\| - 重点说你提到的
*:在所有正则风格里,*都是量词——它的作用是“匹配前面的元素零次或多次”,所以单独写*毫无意义(它会匹配“零个任意字符”,也就是空,结果就是匹配所有行)。要匹配任意字符任意次数,必须写成.*:.匹配任意单个字符,*修饰这个.,这才是你要的“任意内容”。这个点在三种风格里是统一的,不是风格差异,是基础概念没摸透~ - 举个实际例子:
- 匹配包含“abc”或“adc”的行:
grep 'a[bd]c' file.txt([]在BRE里不用转义,本身就是特殊字符) - 匹配连续两个及以上的
a:grep 'a\{2,\}' file.txt(注意大括号也要转义)
- 匹配包含“abc”或“adc”的行:
2. 扩展正则表达式(ERE):更直观的现代款
用grep -E或者egrep就能调用,这玩意儿终于符合我们平时学的“标准正则”逻辑了:
- 大部分特殊元字符不用转义直接用:
+、?、()、|这些直接写就行,不用加反斜杠 - 还是关于
*:作用和BRE完全一样,还是量词,所以要匹配任意内容依然是.*,别再单独写*啦! - 示例:
- 匹配一个或多个
a:grep -E 'a+' file.txt(不用转义+,舒服多了) - 匹配“abc”或“adc”:
grep -E 'a(b|d)c' file.txt(括号和|直接用,逻辑清晰)
- 匹配一个或多个
3. Perl兼容正则表达式(PCRE):功能拉满的进阶款
用grep -P调用,这是正则玩家的终极利器,支持Perl里的所有高级特性:
- 完全兼容ERE的所有语法,还额外加了一堆好用的功能:
- 正向/反向预查:比如
(?=foo)可以匹配后面跟着foo的位置,不用把foo包含在匹配结果里 - 懒惰匹配:默认的
.*是贪婪匹配(尽可能长),加个问号变成.*?就是懒惰匹配(尽可能短) - 特殊字符类:
\d匹配数字、\w匹配单词字符、\s匹配空白符,不用再写[0-9]、[a-zA-Z0-9_]了
- 正向/反向预查:比如
- 示例:
- 匹配以数字开头的行:
grep -P '^\d+' file.txt - 匹配“foo”到“bar”之间最短的内容:
grep -P 'foo.*?bar' file.txt(避免匹配到中间多个bar的情况)
- 匹配以数字开头的行:
快速对比小表格
| 特性/符号 | BRE(默认grep) | ERE(grep -E) | PCRE(grep -P) |
|---|---|---|---|
+(1次或多次) | 需要转义\+ | 直接用+ | 直接用+ |
?(0次或1次) | 需要转义\? | 直接用? | 直接用? |
()(分组) | 需要转义\(\) | 直接用() | 直接用() |
|(或逻辑) | 需要转义\| | 直接用| | 直接用| |
.*(任意内容) | 支持 | 支持 | 支持 |
懒惰匹配.*? | 不支持 | 不支持 | 支持 |
| 预查/特殊字符类 | 不支持 | 不支持 | 支持 |
给你的实用小建议
- 日常用优先选
grep -E(ERE),语法直观,不容易因为转义出错 - 遇到复杂需求(比如预查、懒惰匹配)直接上
grep -P(PCRE),功能够强 - 反复提醒自己:
*是量词,必须跟着一个元素(字符、字符类、分组),单独的*只会匹配空内容,等于没筛选
内容的提问来源于stack exchange,提问作者Calculus Knight
相关产品推荐
相关产品推荐

