正则表达式BRE与ERE对比

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

*
*
+
\+
\+
?
\=
\?
{m,n}
\{m,n}
\{m,n\}
\b *
\< \>
\< \>
(…|…)
\(…\|…\) \(…\|…\)
(…)
\(…\)
\(…\)
\1 \2
\1 \2
\1 \2
awk * + ? {m,n} \< \> (…|…) (…) 不支持
sed * \+ \? \{m,n\} \y \< \> (…|…) (…) \1 \2
注 2:对应的 Unicode 属性请参考本系列文章已经刊发过的关于 Unicode 的部分。
POSIX 字符组的使用有所不同。主要区别在于,PCRE 字符组简记法可以脱离方括号直接 出现,而 POSIX 字符组必须出现在方括号内,所以同样是匹配数字字符,单独出现时,PCRE 中可以直接写『\d』,而 POSIX 字符组就必须写成『[[:digit:]]』。
POSIX 的全称是 Portable Operating System Interface for uniX,它由一系列规范构 成,定义了 UNIX 操作系统应当支持的功能,所以“POSIX 规范的正则表达式”其实只是“关 于正则表达式的 POSIX 规范”,它定义了 BRE(Basic Regular Expression,基本型正则表 达式)和 ERE(Extended Regular Express,扩展型正则表达式)两大流派。在兼容 POSIX 的 UNIX 系统上,grep 和 egrep 之类的工具都遵循 POSIX 规范,一些数据库系统中的正则表达 式也符合 POSIX 规范。
[:upper:]
大写字母字 符
[A-Z]
\p{Lu}
[:word:]* 字母字符 [A-Za-z0-9_]
[\p{L}\p{N}\p{Pc }]
[:xdigit: ]
பைடு நூலகம்
十六进制字 符
[A-Fa-f0-9]
[A-Fa-f0-9]
注 1:标记*的字符组简记法并不是 POSIX 规范中的,但使用很多,一般语言中都提供, 文档中也会出现。
GNU ERE
元|可字以符直不接必使转用义,,支+、持?\、1、(、\2)、{、}、grep –E、GNU awk
为了方便查阅,下面再用一张表格列出基本的正则功能在常用工具中的表示法,其中的 工具 GNU 的版本为准。
常用 Linux/Unix 工具中的表示法
PCRE 记法 vi/vim
grep
*
为了解决字符组中特殊意义字符的转义问题,POSIX 方括号表示法规定,如果要在字符 组中表达字符](而不是作为字符组的结束标记),应当让它紧跟在字符组的开方括号之后, 所以 POSIX 中,正则表达式『[]a]』能匹配的字符就是]和 a;如果要在 POSIX 方括号表示法 中表达字符-(而不是范围表示法),必须将它紧挨在闭方括号]之前,所以『[a-]』能匹配的 字符就是 a 和-。
原因在于,Unix/Linux 下的工具大多采用 POSIX 规范,同时,POSIX 规范又可分为两种 流派(flavor)。所以,首先有必要了解一下 POSIX 规范。
POSIX 规范
常见的正则表达式记法,其实都源于 Perl,实际上,正则表达式从 Perl 衍生出一个显 赫的流派,叫做 PCRE(Perl Compatible Regular Expression),『\d』、『\w』、『\s』 之类的记法,就是这个流派的特征。但是在 PCRE 之外,正则表达式还有其它流派,比如下 面要介绍的 POSIX 规范的正则表达式。
几种 POSIX 流派的说明
流派 说明
工具
BRE
(、)、{、}都必须转义使用,不支持+、?、grep、sed、vi(但 vi 支持
|
这些多选结构和反向引用)
GNU
BRE(、)、{、}、+、?、|都必须转义 使用
GNU
grep、GNU
sed
ERE 元|可字以符直不接必使转用义,,\+1、、?\、2 的(、支)持、不{、确}定、egrep、awk
ERE
在 Linux/Unix 常用工具中,egrep、awk 则属于 ERE 这一派,。虽然 BRE 名为“基本” 而 ERE 名为“扩展”,但 ERE 并不要求兼容 BRE 的语法,而是自成一体。因此其中的元字符 不用转义(在元字符之前添加反斜线会取消其特殊含义),所以『(ab|cd)』就可以匹配字符 串 ab 或者 cd,量词『+』、『?』、『{n,m}』可以直接使用。ERE 并没有明确规定支持反向 引用,但是不少工具都支持『\1』、『\2』之类的反向引用。
BRE
在 Linux/Unix 常用工具中,grep、vi、sed 都属于 BRE 这一派,它的语法看起来比较 奇怪,元字符『(』、『)』、『{』、『}』必须转义之后才具有特殊含义,所以正则表达式 『(a)b』只能匹配字符串 (a)b 而不是字符串 ab;正则表达式『a{1,2}』只能匹配字符串 a{1,2},正则表达式『a\{1,2\}』才能匹配字符串 a 或者 aa。
注:PCRE 中常用\b 来表示“单词的起始或结束位置”,但 Linux/Unix 的工具中,通常 用\<来匹配“单词的起始位置”,用\>来匹配“单词的结束位置”,sed 中的\y 可以同时匹 配这两个位置。
POSIX 字符组
在某些文档中,你还会发现类似『[:digit:]』、『[:lower:]』之类的表示法,它们看 起来不难理解(digit 就是“数字”,lower 就是“小写”),但又很奇怪,这就是 POSIX 字 符组。不仅在 Linux/Unix 的常见工具中,甚至一些变成语言中都出现了这些字符组,为避 免困惑,这里有必要简要介绍它们。
[:blank:]
空格字符和 制表符
[
\t]
[\p{Zs}\t]
[:cntrl:] 控制字符 [\x00-\x1F\x7F]
\p{Cc}
[:digit:] 数字字符 [0-9]
\p{Nd}
[:graph:]
空白字符之 外的字符
[\x21-\x7E]
[^\p{Z}\p{C}]
[:lower:]
小写字母字 符
之所以这么麻烦,是因为这些工具的诞生时间很早,正则表达式的许多功能却是逐步发 展演化出来的,之前这些元字符可能并没有特殊的含义;为保证向后兼容,就只能使用转义。 而且有些功能甚至根本就不支持,比如 BRE 就不支持『+』和『?』量词,也不支持多选结构 『(…|…)』和反向引用『\1』、『\2』…。
不过今天,纯粹的 BRE 已经很少见了,毕竟大家已经认为正则表达式“理所应当”支持 多选结构和反向引用等功能,没有确实太不方便。所以虽然 vi 属于 BRE 流派,但提供了这 些功能。GNU 也对 BRE 做了扩展,支持『+』、『?』、『|』,只是使用时必须写成『\+』、 『\?』、『\|』,而且也支持『\1』、『\2』之类反向引用。这样,GNU 的 grep 等工具虽 然名义上属于 BRE 流,但更确切的名称是 GNU BRE。
[a-z]
\p{Ll}
类似 [:print:] [但:g包ra括ph空:]白,[\x20-\x7E]
字符
\P{C}
[:punct:] 标点符号
[][!"#$%&'()*+,./:;<=>?@\^_`{|} ~-]
[\p{P}\p{S}]
[:space:] 空白字符 [ \t\r\n\v\f]
[\p{Z}\t\r\n\v\f ]
对正则表达式有基本了解的读者,一定不会陌生『\d』、『[a-z]+』之类的表达式,前 者匹配一个数字字符,后者匹配一个以上的小写英文字母。但是如果你用过 vi、grep、awk、 sed 之类 Linux/Unix 下的工具或许会发现,这些工具虽然支持正则表达式,语法却很不一 样,照通常习惯的办法写的『\d』、『[a-z]+』之类的正则表达式,往往不是无法识别就是 匹配错误。而且,这些工具自身之间也存在差异,同样的结构,有时需要转义有时不需要转 义。这,究竟是为什么呢?
POSIX 字符组
POSIX 组
字符
说明
ASCII 语言环境
Unicode 语言环境
[:alnum:] *
字母字符和 数字字符
[a-zA-Z0-9]
[\p{L&}\p{Nd}]
[:alpha:] 字母
[a-zA-Z]
\p{L&}
[:ascii:] ASCII 字符 [\x00-\x7F]
\p{InBasicLatin}
Linux/Unix 下的 POSIX 规范
2011-07-12 15:21 余晟 InfoQ 我要评论(1) 字号:T | T
很多读者一定不会陌生『\d』、『[a-z]+』之类的表达式,但是如果你用过 vi、grep、awk、 sed 之类 Linux/Unix 下的工具或许会发现,这些工具虽然支持正则表达式,语法却很不一 样,照通常习惯的办法写的『\d』、『[a-z]+』之类的正则表达式,往往不是无法识别就是 匹配错误。而且,这些工具自身之间也存在差异,同样的结构,有时需要转义有时不需要转 义。这,究竟是为什么呢?原因在于,Unix/Linux 下的工具大多采用 POSIX 规范
Linux/Unix 下的工具中,一般都可以直接使用 POSIX 字符组,而 PCRE 的字符组简记法 『\w』、『\d』等则大多不支持,所以如果你看到『[[:space:]]』而不是『\s』,一定不 要感到奇怪。
不过,在常用的编程语言中,Java、PHP、Ruby 也支持使用 POSIX 字符组。其中 Java 和 PHP 中的 POSIX 字符组都是按照 ASCII 语言环境进行匹配;Ruby 的情况则要复杂一点,Ruby 1.8 按照 ASCII 语言环境进行匹配,而且不支持『[:word:]』和『[:alnum:]』,Ruby 1.9 按照 Unicode 语言环境进行匹配,同时支持『[:word:]』和『[:alnum:]』。
POSIX 规范也定义了 POSIX 字符组,它近似等价于于 PCRE 的字符组简记法,用一个有 直观意义的名字来表示某一组字符,比如 digit 表示“数字字符”,alpha 表示“字母字符”。
不过,POSIX 中还有一个值得注意的概念:locale(通常翻译为“语言环境”)。它是一 组与语言和文化相关的设定,包括日期格式、货币币值、字符编码等等。POSIX 字符组的意 义会根据 locale 的变化而变化,下面的表格介绍了常见的 POSIX 字符组在 ASCII 语言环境 与 Unicode 语言环境下的意义,供大家参考。
在 POSIX 规范中,『[a-z]』、『[aeiou]』之类的记法仍然是合法的,其意义与 PCRE 中的字符组也没有区别,只是这类记法的准确名称是 POSIX 方括号表达式(bracket expression),它主要用在 Unix/Linux 系统中。POSIX 方括号表示法与 PCRE 字符组的最主 要差别在于:POSIX 字符组中,反斜线\不是用来转义的。所以 POSIX 方括号表示法『[\d]』 只能匹配\和 d 两个字符,而不是『[0-9]』对应的数字字符。
GNU 出品的 egrep 等工具就属于 ERE 流(更准确的名字是 GNU ERE),但因为 GNU 已经对 BRE 做了不少扩展,所谓的 GNU ERE 其实只是个说法而已,它有的功能 GNU BRE 都有了,只 是元字符不需要转义而已。
下面的表格简要说明了几种 POSIX 流派的区别[1](其实,现在的 BRE 和 ERE 在功能上并 没有什么区别,主要的差异是在元字符的转义上)。
相关文档
最新文档