PCRE正则语法
PHP Manual

子组(子模式)

子组通过圆括号分隔界定, 并且它们可以嵌套. 将一个模式中的一部分标记为子组(子模式)主要是来做两件事情:

  1. 将可选分支局部化. 比如, 模式cat(arcat|erpillar|)匹配”cat”, “cataract”, “caterpillar”中的一个, 如果没有圆括号的话, 它匹配的则是”cataract”, “erpillar”以及空字符串.

  2. 将子组设定为捕获子组(向上面定义的). 当整个模式匹配后, 目标字符串中匹配子组的部分将会通过 pcre_exec()()ovector参数回传给调用者. 左括号从左至右出现的次序就是对应子组的下标(从1开始), 可以通过这些下标数字来获取捕获子模式匹配结果.

比如, 如果字符串”the red king”使用模式((red|white) (king|queen))进行匹配, 模式匹配到的结果是array(“red king”, ”red king”, “red”, “king”)的形式, 其中第0个元素是整个模式匹配的结果, 后面的三个元素依次为三个子组匹配的结果. 它们的下表分别为1, 2, 3.

事实上, 圆括号履行的两种功能并不总是有用的. 经常我们会有一种需求需要使用子组进行分组, 但又不需要(单独的)捕获它们. 在子组定义的左括号后面紧跟字符串”?:”会使得该子组不被单独捕获, 并且不会对其后子组序号的计算产生影响. 比如, 如果字符串”the white queen”匹配模式((?:red|white) (king|queen)), 匹配到的结果会是array(“white queen”, “white queen”, “white queen”), 只捕获了最外面的和king|queen这两个子组. 捕获子组序号的最大值是99, 最大允许拥有的所有子组(包括捕获的和非捕获的)的最大数量为200.

为了方便简写, 如果需要在非捕获子组开始位置设置选项, 选项字母可以位于?和:之间, 比如:

(?i:saturday|sunday)
(?:(?i)saturday|sunday)

上面两种写法实际上是相同的模式. 因为可选分支会从左到右尝试每个分支, 并且选项没有在子模式结束前被重置, 并且由于选项的设置会穿透对后面的其他分支产生影响, 因此, 上面的模式都会匹配”SUNDAY”以及”Saturday”

在php 4.3.3中, 可以对子组使用(?P<name>pattern)的语法进行命名. 这个子模式将会在匹配结果中同时以其名称和顺序(数字下标)出现. php 5.2.2中又增加了两种味子组命名的语法: (?<name>pattern)(?’name’pattern)

有时需要多个匹配可以在一个正则表达式中选用子组. 为了让多个子组可以共用一个后向引用数字的问题, (?|语法允许复制数字. 考虑下面的正则表达式匹配Sunday:

(?:(Sat)ur|(Sun))day

这里当后向引用1空时Sun存储在后向引用2中. 当后向引用2不存在的时候Sat存储在后向引用1中. 使用 (?|修改模式来修复这个问题:

(?|(Sat)ur|(Sun))day

使用这个模式, SunSat都会被存储到后向引用1中.


PCRE正则语法
PHP Manual