Table 9-19. ARE 嵌入选项字母
选项 描述
b 剩下的 RE 是 BRE
c 大小写敏感匹配(覆盖操作符类型)
e 剩下的 RE 是 ERE
i 大小写不敏感匹配(参阅 Section 9.7.3.5) (覆盖操作符类型)
m n 的历史同义词
n 新行敏感匹配(参阅 Section 9.7.3.5)
p 部分新行敏感匹配(参阅 Section 9.7.3.5)
q 重置 RE 为一个文本("引起")字串,所有都是普通字符
s 非新行敏感匹配(缺省)
t 紧语法(缺省,见下文)
w 反转部分新行敏感("怪异")匹配(参阅 Section 9.7.3.5)
x 扩展的语法(见下文)
嵌入地选项在终止其序列的 ) 发生作用。他们只在 ARE 的开始处起作用 (如果有,则在任何 ***: 指示器后面)。
除了通常的(紧)RE 语法,(这种情况下所有字符都重要), 还有一种扩展语法,可以通过声明嵌入的 x 选项获得。 在扩展语法里,RE 中的空白字符被忽略,就像那些在 # 和新行之间 的字符一样。这样就允许我们给一个复杂的 RE 分段和注释。不过这个基本规则 上有三种例外:
*
前置了 \ 的空白字符或者 # 保留
*
方括弧里的空白或者 # 保留
*
在多字符符号里面不能出现空白和注释,比如 (?:。
在这里,空白是空格,水平制表符,新行,和任何属于 space (空白)字符表的字符。
最后,在 ARE 里,方括弧表达式外面,序列 (?#ttt) (这里的 ttt 是任意不包含 ) 的文本)是一个注释, 完全被忽略。同样,这样的东西是不允许出现在多字符符号的字符中间的, 比如 (?:。这样的注释是比有用的机制的更久远的历史造成的, 他们的用法已经废弃了;我们应该使用扩展语法代替他。
如果声明了一个初始化的 ***= 指示器,那么所有这些元语法 扩展都不能使用,因为这样表示把用户输入当作一个文本字串 而不是 RE 对待。
9.7.3.5. 正则表达式匹配规则
在 RE 可以匹配给出的字串中多于一个子字串的情况下, RE 匹配字串中最靠前的那个子字串。如果 RE 可以匹配在那个位置开始 的多个子字串,要么是取最长的子字串,要么是最短的,具体哪种, 取决于 RE 是贪婪的 还是 非贪婪的。
一个 RE 是否贪婪取决于下面规则:
*
大多数原子,以及所有约束,都没有贪婪属性(因为它们毕竟无法匹配个数变化的文本)。
*
在一个 RE 周围加上圆括弧并不会改变其贪婪性。
*
一个带一个固定重复次数的量词 ({m} 或者 {m}?) 之量化的原子和原子自身有着同样的贪婪性(可能是没有)。
*
一个带其他普通的量词(包括 {m,n} 中 m 等于 n 的情况)量化的原子是贪婪的(首选最长匹配)。
*
一个带非贪婪量词(包括 {m,n}? 中 m 等于 n 的情况)之量化原子是非贪婪的(首选最短匹配)。
*
一个分支 — 也就是说,一个没有顶级 | 操作的 RE — 和它里面的第一个有贪婪属性的量化原子有着同样的贪婪性。
*
一个由 | 操作符连接起来的两个或者更多分支组成的 RE 总是贪婪的。
上面的规则所描述的贪婪属性不仅仅适用于独立的量化原子, 而且也适用于包含量化原子的分支和整个 RE。这里的意思是, 匹配是按照分支或者整个 RE 作为一个整体匹配最长或者最短的子字串的可能。 一旦整个匹配的长度确定,那么匹配任意子表达式的部分就基于该子表达式的贪婪属性进行判断, 在 RE 里面靠前的子表达式的优先级高于靠后的子表达式。
一个表达这些的例子:
SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})');
Result: 123
SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
Result: 1
在第一个例子里,RE 作为整体是贪婪的,因为 Y* 是贪婪的。 它可以匹配从 Y 开始的东西,并且它匹配从这个位置开始的最长的字串, 也就是,Y123。输出是这里的圆括弧包围的部分,或者说是 123。 在第二个例子里, RE 总体上是一个非贪婪的 RE,因为 Y*? 是非贪婪的。 它可以匹配从 Y 开始的最短的子字串,也就是说 Y1。 子表达式 [0-9]{1,3} 是贪婪的,但是它不能修改总体匹配长度的决定; 因此它被迫只匹配 1。
简单说,如果一个 RE 同时包含贪婪和非贪婪的子表达式, 那么总匹配长度要么是最长可能,要么是最短可能,取决于给整个 RE 赋予的贪婪属性。 给子表达式赋予的贪婪属性只影响在这个匹配里,各个子表达式之间相互允许"吃进"的多少。
量词 {1,1} 和 {1,1}? 可以分别用于在一个子表达式或者整个 RE 上强制贪婪或者非贪婪。
匹配长度是以字符衡量的,而不是集合的元素。一个空字串会被认为比什么都不匹配长。 比如:bb* 匹配 abbbc 的中间三个字符; (week|wee)(night|knights) 匹配 weeknights 的所有十个字符; 而 (.*).* 匹配 abc的时候,圆括弧包围的子表达式 匹配所有三个字符;而如果用 (a*)* 匹配 bc,那么 RE 和圆括弧 子表达式都匹配整个字串。
如果声明了大小写无关的匹配,那么效果就好像把所有字母上的 大小写区别取消了一样。如果一个存在大小写差别的字母以一个 普通字符的形式出现在方括弧表达式外面,那么它实际上被转换成 一个包含大小写的方括弧表达式,也就是说,x 变成 [xX]。 如果它出现在一个方括弧表达式里面,那么它的所有大小写的同族都被加入 方括弧表达式中,也就是说,[x] 变成 [xX], 而 [^x] 变成 [^xX]。
如果声明了新行敏感匹配,. 和使用^的方括弧表达式 将永远不会匹配新行字符(这样,匹配就绝对不会夸新行,除非 RE 明确地安排了 这样的情况)并且^ 和$ 除了分别匹配 字串开头和结尾之外,还将分别匹配新行后面和前面 的空字串。但是 ARE 逃逸 \A 和 \Z 仍然只匹配字串的开头和结尾。
如果声明了部分新行敏感匹配,那么它影响 . 和方括弧表达式, 这个时候和新行敏感匹配一样,但是不影响 ^ 和 $。
如果声明了反转新行敏感匹配,那么它影响 ^ 和 $, 作用和新行敏感匹配里一样,但是不影响 . 和方括弧表达式。 这个没什么太多用途,只是为了对称提供的。
9.7.3.6. 限制和兼容性
在这个实现里,对 RE 的长度没有特别的限制,但是,那些希望能够 有很好移植行的程序应该避免写超过 256 字节的 RE,因为 POSIX 兼容 的实现可以拒绝接受这样的 RE。
ARE 实际上和 POSIX ERE 不兼容的唯一的特性是在方括弧表达式里 \ 并不 失去它特殊的含义。所有其它 ARE 特性都使用在 POSIX ERE 里面是非法或者是 未定义、未声明效果的语法;指示器的 *** 就是再 POSIX 的 BRE 和 ERE 之外的语法。
许多 ARE 扩展都是从 Perl 那里借来的,但是有些我做了修改,清理了 一下,以及一些Perl里没有出现的扩展。要注意的不兼容包括 \b, \B,对结尾的新行缺乏特别的处理,对那些新行敏感匹配的附加的 补齐方括弧表达式,在前瞻约束里对圆括弧和方括弧引用的限制,以及最长/最短 匹配(而不是第一匹配)语义。
PostgreSQL 7.4 之前的版本里的 ARE 和 ERE 存在两个非常 显著的不兼容:
*
在 ARE 里,后面跟着一个字母数字的 \ 要么是一个逃逸,要么是错误, 但是在以前的版本里,她只是写那个字母数字的另外一种方法。这个应该不是什么问题, 因为在以前的版本里没有什么原因让我们写这样的序列。
*
在 ARE 里,\在 []里还是一个特殊字符, 因此在方括弧表达式里的一个文本 \ 必须写成 \\。
虽然这些区别对大多数应用都来说都可能不是问题, 但必要时你可以通过设置 regex_flavor 为 extended 来避免这些问题。
9.7.3.7. 基本正则表达式
BRE 在几个方面和 ERE 不太一样。|,+,和 ? 都是普通字符,它们没有等效的功能替换。范围的分隔符是 \{ 和 \}, 因为 { 和 } 本身是普通字符。嵌套的子表达式的圆括弧是 \( 和 \),因为 ( 和 ) 自身是普通字符。 除非在 RE 开头或者是圆括弧封装的子表达式开头,^ 都是普通字符, 除非在 RE 结尾或者是圆括弧封装的子表达式的结尾,$ 是一个普通字符, 而如果 * 出现在 RE 开头或者是圆括弧封装的子表达式开头 (前面可能有 ^ ),那么它是个普通字符。 最后,可以用单数字的后引用,以及 \< 和 \> 分别是 [[:<:]] 和 [[:>:]]的同义词;没有其它的逃逸。