分支重置组

分支重置组


Perl 5.10引入了一个新的正则表达式功能,称为分支重置组。JGsoft V2和PCRE 7.2及更高版本也支持此功能,PHP,Delphi和R具有基于PCRE的正则表达式功能的语言也支持此功能。Boost将它们添加到1.42版的ECMAScript语法中。           

分支重置组内的选择项共享相同的捕获组。语法是(?|regex),其中(?|打开组,而regex可以是任意的正则表达式。如果不使用任何选择项或捕获分支重置组内的组,则其特殊功能将不起作用。那么它将作为一个非捕获组。        

正则表达式(?|(a)|(b)|(c))由一个带有三个选择项的分支重置组组成。此正则表达式匹配a ,b或c 。正则表达式只有一个捕获组,编号为1,由所有三个选择项共享。匹配结束后,$1存储a ,b或c 。          

将此与正则表达式(a)|(b)|(c)进行比较。此正则表达式也匹配a ,b或c 。但是它具有三个捕获组。匹配结束后,$1保留a或什么都不保留,$2保留b或什么都不保留,而$3保留c或什么都不保留。                 

捕获分支重置组中的组的反向引用可以像我们期望的那样工作。(?|(a)|(b)|(c))\1匹配aa,bb或cc 。由于分支重置组中只有一个选择项可以匹配,因此参与匹配的选择项将确定捕获组存储的文本,从而确定由反向引用匹配的文本。       分支重置组中的选择项不必具有相同数量的捕获组。(?|abc|(d)(e)(f)|g(h)i)具有三个捕获组。当此正则表达式匹配abc时,所有三个组均为空。当def被匹配时,$1持有d ,$2持有e,$3持有f。当ghi被匹配时,$1保持h,而另两个为空。                     

我们可以在分支重置组之前和之后拥有捕获组。分支重置组之前的组照常编号。分支重置组中的组是从分支重置组之前的组开始编号的,每个分支重置组都会重置该编号。分支重置组之后的组从具有最多组的选择项开始编号,即使这不是最后的选项,编号也是如此执行。因此(x)(?|abc|(d)(e)(f)|g(h )i)(y)定义了五个捕获组。(x)是组1,(d)(h)是组2,(e)是组3,(f)是组4,(y)是组5。              

在分支重置组中为捕获组命名


我们可以在分支重置组中使用命名的捕获组。如果这样做,则应为使用相同编号的组使用相同的名称。否则,我们将在Perl或Boost中得到意想不到的结果。从版本8.00开始,PCRE仅可靠地支持分支重置组中的命名组。这意味着Delphi仅从XE7开始,而PHP从5.2.14版本开始。  

(?'before'x)(?|abc|(?'left'd)(?'middle'e)(?'right'f)|g(?'left'h)i)(?'after'y)与以前的正则表达式相同。它将五个组命名为“before”,“left”,“middle”,“right”和“after”。请注意,由于第三个选择项只有一个捕获组,因此该名称必须是其他选择项中第一个捕获组的名称。 

如果我们在某些选择项中省略了名称,则组仍将与其他选择项共享名称。在正则表达式(?'before'x)(?|abc|(?'left'd)(?'middle'e)(?'right'f)|g(h)i)(?'after'y)该组(h)仍被命名为“ left”,因为分支重置组使其共享(?'left'd)的名称和编号。

准确天数的日和月


现在该举一个更实际的例子了。这两个正则表达式与m/d或mm/dd格式的日期匹配。它们同时过滤了无效的日期,例如2/31。下面的正则表达式可以实现:

^(?:(0?[13578]|1[02])/(3[01]|[12][0-9]|0?[1-9]) # 31 days
 |  (0?[469]|11)/(30|[12][0-9]|0?[1-9])         # 30 days
 |  (0?2)/([12][0-9]|0?[1-9])                   # 29 days
 )$

第一个版本使用非捕获组(?:...)对备用方案进行分组。它具有六个单独的捕获组。$1和$2保留月份和日期为31天的月份。$3和$4它们保留30天的几个月。$5和$6仅用于二月份。  

^(?|(0?[13578]|1[02])/(3[01]|[12][0-9]|0?[1-9]) # 31 days
 |  (0?[469]|11)/(30|[12][0-9]|0?[1-9])         # 30 days
 |  (0?2)/([12][0-9]|0?[1-9])                   # 29 days
 )$

第二个版本使用分支重置组(?|…)对备选方案进行分组并合并其捕获组。第四个字符是这两个正则表达式之间的唯一区别。现在只有两个捕获组。当找到匹配项时,无论月份中的天数如何,$1始终保留月份,而2始终保留日期。        

查看笔记

扫码一下
查看教程更方便