模式语法
(No version information available,might only be in SVN)
模式语法 — 解说 Perl 兼容正则表达式的语法
说明
PCRE 库是一组用和 Perl 5 相同的语法和语义实现了正则表达式模式匹配的函数,不过有少许区别(见下面)。当前 PCRE 的实现是与 Perl 5.005 相符的。
与 Perl 的区别
这里谈到的区别是就 Perl 5.005 来说的。
- 默认情况下,空白字符是 C 语言库函数 isspace() 所能识别的任何字符,尽管有可能与别的字符类型表编译在一起。通常 isspace() 匹配空格,换页符,换行符,回车符,水平制表符和垂直制表符。Perl 5 不再将垂直制表符包括在空白字符中了。事实上长久以来存在于 Perl 文档中的转义序列 v 从未被识别过,不过该字符至少到 5.002 为止都被当成空白字符的。在 5.004 和 5.005 中 s 不匹配此字符。
- PCRE 不允许在向前断言中使用重复的数量符。Perl 允许这样,但可能不是你想象中的含义。例如,(?!a){3} 并不是断言下面三个字符不是“a”,而是断言下一个字符不是“a”三次。
- 捕获出现在排除模式断言中的子模式虽然被计数,但并未在偏移向量中设定其条目。Perl 在匹配失败前从此种模式中设定其数字变量,但只在排触摸式断言只包含一个分支时。
- 尽管目标字符串中支持二进制的零字符,但不能出现在模式字符串中,因为它被当作普通的 C 字符串传递,以二进制零终止。转义序列“x00”可以在模式中用来表示二进制零。
- 不支持下列 Perl 转义序列:l,u,L,U。事实上这些是由 Perl 的字符串处理来实现的,并不是模式匹配引擎的一部分。
-
不支持 Perl 的 G 断言,因为这和单个的模式匹配无关。
- 很明显,PCRE 不支持 (?{code}) 结构。
-
当部分模式重复的时候,有关 Perl 5.005_02 捕获字符串的设定有些古怪的地方。举例说,用模式 /^(a(b)?)+$/ 去匹配 "aba" 会将 $2 设为 "b",但是用模式 /^(aa(bb)?)+$/ 去匹配 "aabbaa" 会使 $2 无值。然而,如果把模式改成 /^(aa(b(b))?)+$/,则 $2(和 $3)就有值了。在 Perl 5.004 中以上两种情况下 $2 都会被赋值,在 PCRE 中也是 TRUE。如果以后 Perl 改了,PCRE 可能也会跟着改。
- 另一个未解决的矛盾是 Perl 5.005_02 中模式 /^(a)?(?(1)a|b)+$/ 能匹配上字符串 "a",但是 PCRE 不会。然而,在 Perl 和 PCRE 中用 /^(a)?a/ 去匹配 "a" 会使 $1 没有值。
-
PCRE 提供了一些对 Perl 正则表达式机制的扩展:
- 尽管向后断言必须匹配固定长度字符串,但每个向后断言的分支可以匹配不同长度的字符串。Perl 5.005 要求所有分支的长度相同。
- 如果设定了 PCRE_DOLLAR_ENDONLY 而没有设定 PCRE_MULTILINE,则 $ 元字符只匹配字符串的最末尾。
- 如果设定了 PCRE_EXTRA,反斜线后面跟一个没有特殊含义的字母会出错。
- 如果设定了 PCRE_UNGREEDY,则重复的数量符的 greed 被反转,即,默认时不是 greedy,但如果后面跟上一个问号就变成 greedy 了。
正则表达式详解
介绍
下面说明 PCRE 所支持的正则表达式的语法和语义。Perl 文档和很多其它书中也解说了正则表达式,有的书中有很多例子。Jeffrey Friedl 写的“Mastering Regular Expressions”,由 O'Reilly 出版社发行(ISBN 1-56592-257-3),包含了大量细节。这里的说明只是个参考文档。
正则表达式是从左向右去匹配目标字符串的一组模式。大多数字符在模式中表示它们自身并匹配目标中相应的字符。作为一个小例子,模式 The quick brown fox 匹配了目标字符串中与其完全相同的一部分。
元字符
正则表达式的威力在于其能够在模式中包含选择和循环。它们通过使用元字符来编码在模式中,元字符不代表其自身,它们用一些特殊的方式来解析。
有两组不同的元字符:一种是模式中除了方括号内都能被识别的,还有一种是在方括号内被识别的。方括号之外的元字符有这些:
-
-
有数种用途的通用转义符
-
^
-
断言目标的开头(或在多行模式下行的开头,即紧随一换行符之后)
-
$
-
断言目标的结尾(或在多行模式下行的结尾,即紧随一换行符之前)
-
.
-
匹配除了换行符外的任意一个字符(默认情况下)
-
[
-
字符类定义开始
-
]
-
字符类定义结束
-
|
-
开始一个多选一的分支
-
(
-
子模式开始
-
)
-
子模式结束
-
?
-
扩展 ( 的含义,也是 0 或 1 数量限定符,以及数量限定符最小值
-
*
-
匹配 0 个或多个的数量限定符
-
+
-
匹配 1 个或多个的数量限定符
-
{
-
最少/最多数量限定开始
-
}
-
最少/最多数量限定结束
模式中方括号内的部分称为“字符类”。字符类中可用的元字符为:
-
-
通用转义字符
-
^
-
排除字符类,但仅当其为第一个字符时有效
-
-
-
指出字符范围
-
]
-
结束字符类
以下说明了每一个元字符的用法。
反斜线()
反斜线字符有几种用途。首先,如果其后跟着一个非字母数字字符,则取消该字符可能具有的任何特殊含义。此种将反斜线用作转义字符的用法适用于无论是字符类之中还是之外。
例如,如果想匹配一个“*”字符,则在模式中用“*”。这适用于无论下一个字符是否会被当作元字符来解释,因此在非字母数字字符之前加上一个“”来指明该字符就代表其本身总是安全的。尤其是,如果要匹配一个反斜线,用“”。
Note: 单引号或双引号括起来的 PHP 字符串中的反斜线有特殊含义。因此必须用正则表达式的 来匹配 ,而在 PHP 代码中要用 "\" 或 '\'。
如果模式编译时加上了 PCRE_EXTENDED 选项,模式中的空白字符(字符类中以外的)以及字符类之外的“#”到换行符之间的字符都被忽略。可以用转义的反斜线将空白字符或者“#”字符包括到模式中去。
反斜线的第二种用途提供了一种在模式中以可见方式去编码不可打印字符的方法。并没有不可打印字符出现的限制,除了代表模式结束的二进制零以外。但用文本编辑器来准备模式的时候,通常用以下的转义序列来表示那些二进制字符更容易一些:
-
a
-
alarm,即 BEL 字符(0x07)
-
cx
-
"control-x",其中 x 是任意字符
-
e
-
escape(0x1B)
-
f
-
换页符 formfeed(0x0C)
-
n
-
换行符 newline(0x0A)
-
r
-
回车符 carriage return(0x0D)
-
t
-
制表符 tab(0x09)
-
xhh
-
十六进制代码为 hh 的字符
-
ddd
-
八进制代码为 ddd 的字符,或 backreference
“cx”的精确效果如下:如果“x”是小写字母,则被转换为大写字母。接着字符中的第 6 位(0x40)被反转。从而“cz”成为 0x1A,但“c{”成为 0x3B,而“c;”成为 0x7B。
在“x”之后最多再读取两个十六进制数字(其中的字母可以是大写或小写)。在 UTF-8 模式下,允许用“x{...}”,花括号中的内容是表示十六进制数字的字符串。原来的十六进制转义序列 xhh 如果其值大于 127 的话则匹配了一个双字节 UTF-8 字符。
在“