本网站上的更多内容 |
简介 |
正则表达式快速入门 |
正则表达式教程 |
替换字符串教程 |
应用程序和语言 |
正则表达式示例 |
正则表达式参考 |
替换字符串参考 |
书评 |
可打印 PDF |
关于本网站 |
RSS 源和博客 |
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 中得到不良行为。PowerGREP 将不匹配的组名视为错误。PCRE 仅从版本 8.00 开始可靠地支持分支重置组内的命名组。这意味着 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”。请注意,由于第 3 个备选项只有一个捕获组,因此它必须是其他备选项中第一个组的名称。
如果你在某些备选项中省略名称,则这些组仍将与其他备选项共享名称。在正则表达式 (?'before'x)(?|abc|(?'left'd)(?'middle'e)(?'right'f)|g(h)i)(?'after'y) 中,组 (h) 仍被命名为“left”,因为分支重置组使其与 (?'left'd) 的名称和编号相同。
在 Perl、PCRE 和 Boost 中,当你希望不同备选项中的组具有相同的名称时,最好使用分支重置组。这是在 Perl、PCRE 和 Boost 中确保具有相同名称的组实际上是同一个组的唯一方法。
在 PowerGREP 中,具有相同名称的组始终被视为同一个组。因此,在 PowerGREP 中使用带名称的捕获组时,你实际上不需要使用分支重置组。
是时候进行一个更实际的示例了。这两个正则表达式匹配 m/d 或 mm/dd 格式的日期。它们排除了无效日期,例如 2/31。
^(?:(0?[13578]|1[02])/(3[01]|[12][0-9]|0?[1-9]) # 31 天
| (0?[469]|11)/(30|[12][0-9]|0?[1-9]) # 30 天
| (0?2)/([12][0-9]|0?[1-9]) # 29 天
)$
第一个版本使用一个非捕获组 (?:…)对备选方案进行分组。它有六个单独的捕获组。对于有 31 天的月份,$1 和 $2 保存月份和日期。对于有 30 天的月份,$3 和 $4 保存月份和日期。对于 2 月,$5 和 $6 仅用于 2 月。
^(?|(0?[13578]|1[02])/(3[01]|[12][0-9]|0?[1-9]) # 31 天
| (0?[469]|11)/(30|[12][0-9]|0?[1-9]) # 30 天
| (0?2)/([12][0-9]|0?[1-9]) # 29 天
)$
第二个版本使用分支重置组 (?|…) 对备选项进行分组并合并其捕获组。第 4 个字符是这两个正则表达式之间的唯一区别。现在只有两个捕获组。它们在三个备选项之间共享。找到匹配项时,$1 始终保存月份,$2 始终保存日期,而不管该月份有多少天。
| 快速入门 | 教程 | 工具和语言 | 示例 | 参考 | 书籍评论 |
| 简介 | 目录 | 特殊字符 | 不可打印字符 | 正则引擎内部 | 字符类 | 字符类减法 | 字符类交集 | 简写字符类 | 点 | 锚点 | 单词边界 | 交替 | 可选项 | 重复 | 分组和捕获 | 反向引用 | 反向引用,第 2 部分 | 命名组 | 相对反向引用 | 分支重置组 | 自由间距和注释 | Unicode | 模式修饰符 | 原子分组 | 占有量词 | 前瞻和后顾 | 前瞻和后顾,第 2 部分 | 将文本保留在匹配之外 | 条件 | 平衡组 | 递归 | 子例程 | 无限递归 | 递归和量词 | 递归和捕获 | 递归和反向引用 | 递归和回溯 | POSIX 方括号表达式 | 零长度匹配 | 继续匹配 |
页面 URL:https://regexper.cn/branchreset.html
页面上次更新时间:2021 年 8 月 21 日
网站上次更新时间:2024 年 3 月 15 日
版权所有 © 2003-2024 Jan Goyvaerts。保留所有权利。