正则表达式简介

使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。

常见的正则表达式记法都源于 Perl,正则表达式从 Perl 衍生出一个显赫的流派,叫做 PCRE(Perl Compatible Regular Expression), \d\w\s 之类的记法,就是这个流派的特征。但是在 PCRE 之外,正则表达式还有其它流派,比如 POSIX。

POSIX,Portable Operating System Interface for uniX,它由一系列规范构成,定义了 UNIX 操作系统应当支持的功能,所以 “POSIX规范的正则表达式 其实只是 “关于正则表达式的 POSIX 规范,它定义了 BRE 和 ERE 两大流派。在兼容 POSIX 的 UNIX 系统上,grep 和 egrep 之类的工具都遵循 POSIX 规范,一些数据库系统中的正则表达式也符合 POSIX 规范。

  • Basic Regular Expression,BRE,基本正则表达式
  • Extended Regular Express,ERE,扩展型正则表达式

现在的 BRE 和 ERE 在功能上并没有什么区别,主要的差异是在元字符的 转义 上。

几种 POSIX 流派

流派 说明 工具  
BRE (、)、{、}都必须转义使用,不支持+、?、| grep、sed、vi(vi 支持这些多选结构和反向引用)  
GNU BRE (、)、{、}、+、?、 都必须转义使用 GNU grep、GNU sed
ERE 元字符不必转义,+、?、(、)、{、}、 可以直接使用,\1、\2 的支持不确定 egrep、awk
GNU ERE 元字符不必转义,+、?、(、)、{、}、 可以直接使用,支持 \1、\2 grep –E、GNU awk

RE 在常用工具中的表示法

PCRE记法 vi/vim grep awk sed
* * * * *
+ \+ \+ + \+
? \= \? ? \?
{m,n} \{m,n} \{m,n\} {m,n} \{m,n\}
\b * \< \> \< \> \< \> \y \< \>
(…|…) …∥… …∥… (…|…) (…|…)
(…) (…) (…)
\1 \2 \1 \2 \1 \2 不支持 \1 \2

BRE

grep、vi、sed 都属于 BRE,元字符 (){} 必须转义,如 a\{1,2\} 匹配字符串 a 或 aa。

早期的 BRE 不支持 +? 量词,也不支持多选结构 (…|…) 和反向引用 \1\2 …。

纯粹的 BRE 已经很少见了,GNU 对 BRE 做了扩展,支持 +?| ,只是使用时必须写成 \+\?\| ,而且也支持 \1\2 之类反向引用。这样,GNU 的 grep 等工具虽然名义上属于 BRE 流,但更确切的名称是 GNU BRE。

RE 字符 匹配 意义
^word wordpress is good 字符串在行首
word$ not a word 字符串在行尾
e.e eve eae eee e e e 与 e 中间一定有一个字符
\' Im` 含单引号(转义)
es* e es ess esss essss e 后面可以有多个重复的s,也可以没有
^a.* a a alk apk 以 a 开头的任意字符
l[aoiu]st last lost list lust [ ] 只代表一个待查的字符
[A-Z] W E H N P O 字符集(LANG=C),所有大写字母
[^a-z] 5 # E ( 否定字符集,非小写字母
o\{2\} foot cool blood gooooogle 连续两个 o
go\{2,4\}gle google gooogle goooogle 2 ~ 4 个 o 的 google
go\{2,\}gle gooooogle goooooooooogle 2 个 o 以上的 google

ERE

egrep、awk 属于 ERE 这一派,。ERE 并不要求兼容 BRE 的语法,而是自成一体。因此其中的元字符不用转义,量词 +?{n,m} 可以直接使用。ERE 没有明确规定支持反向引用,但是很多工具都支持 \1\2 之类的反向引用。

GNU 出品的 egrep 等工具就属于 ERE 流(更准确的名字是GNU ERE),但因为 GNU 已经对 BRE 做了不少扩展,所谓的 GNU ERE 其实只是个说法而已,它有的功能 GNU BRE 都有了,只是元字符不需要转义而已。

POSIX 正则表达式规范

BRE 要求通配符 (){} 写成和 \{\},ERE 中无需如此。

ERE 增加支持 ?+|,去除了通配符 (){}

POSIX 正则表达式的标准语法经常坚持使用 附加的语法 来支持特殊应用。虽然 POSIX.2 没有实现一些具体的细节,BRE 和 ERE 提供被很多工具使用的标准。

基本通配符

通配符 描述
. 匹配任何一个单字符(许多应用不包括换行符,但是假设包括换行符也是安全的)。在大中小括号中,该通配符只匹配字符 .,例如,a.c 匹配 abc,但是 [a.c] 只匹配 a.c。要匹配 . 不能使用 \.,因为 \. 的作用与 . 一样,应该使用 [.] 来匹配 a.c 中的点。
[ ] 只匹配中括号内的一个字符。例如 [abc] 匹配 abc。[a-z] 匹配小写的 az。这些格式可以混合使用:[abcx-z] 匹配 a,b,c,x,y,z 与 [a-cx-z] 的效果相同。
  - 如果出现在 [] 的开头或结尾,表示匹配字符 -,例如 [^-abc],[-abc] ,[abc-]。注意不能使用 \
  ] 可以出现在中括号中的第一个位置,例如 []abc] 或 [^]abc]
[^ ] 匹配单个字符,该字符不能包含在中括号中。例如,[^abc] 匹配任何除 a,b,c 外的字符。[^a-z] 匹配任何除 a-z 的字符。同理,字符与范围标识可以混合使用,例如,[^a-cx-z]。
^ 匹配字符串的开头。在基于行的工具中,匹配每一行的开头。
$ 匹配字符串的结尾或者换行符的前一个位置。在基于行的工具中,匹配每一行的结尾。
( ) 定义一个子表达式。圆括号在整体匹配完后进行匹配。子表达式也叫做块或组。BRE模式需要写成 ( )
\n 匹配第 n(1<=n<=9) 个子表达式。POSIX.2 对该通配符的定义很模糊,有的工具允许引用大于 9 的子表达式。
* 匹配前一个元素 0 次或多次。例如,ab*c 匹配 ac,abc,abbbbbc 等。[xyz]* 匹配 ` ,x,y,z,zx,zyx,xyzzy 等。(ab)\* 匹配 ,ab,abab` 等。
{m,n} 匹配前一个元素至少 m 次,至多 n 次。例如,a{3,5} 匹配 aaa,aaaa,aaaaa。BRE 模式需要写成 {m,n}

ERE

在 ERE 中,反斜杠 \ 用来对通配符进行转义,所以 BRE 中的 \(\) 在 ERE 中改为 ()\{\} 改为 {}。 ERE 移除了 \n 通配符,并添加了如下通配符。

通配符 描述
? 匹配前一个元素 0 或 1 次。ab?c 匹配 ac,abc
+ 匹配前一个元素 1 次或多次。ab+c 匹配 abc,abbc 等,但是不能匹配 ac。
| 匹配前一个表达式或后一个表达式。abc|def 匹配 abc,def。

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}
[:blank:] 空格字符和制表符 [ \t] [\p{Zs}\t]
[:cntrl:] 控制字符 [\x00-\x1F\x7F] \p{Cc}
[:digit:] 数字字符 [0-9] \p{Nd}
[:graph:] 空白字符之外的字符 [\x21-\x7E] [^\p{Z}\p{C}]
[:lower:] 小写字母字符 [a-z] \p{Ll}
[:print:] 类似[:graph:],但包括空白字符 [\x20-\x7E] \P{C}
[:punct:] 标点符号 }~-] [\p{P}\p{S}]
[:space:] 空白字符 [ \t\r\n\v\f] [\p{Z}\t\r\n\v\f]
[: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]

标记 * 的字符组简记法并不是 POSIX 规范中的,但使用很多,一般语言中都提供,文档中也会出现。

Linux/Unix 下的工具中,一般都可以直接使用 POSIX 字符组,而 PCRE 的字符组简记法 \w\d 等则大多不支持

语系对正则表达式的影响

不同语系的 编码数据 不同,会造成数据截取结果的差异。

编码顺序的区别:

LANG=C 时: 0 1 2 3 4 … A B C D … Z a b c d …z

LANG=zh_TW 时: 0 1 2 3 4 … a A b B c C d D … z Z