命名捕获组

一些正则表达式风格允许命名捕获组。你可以在后续代码中按名称引用这些组,而不是通过数字索引引用这些组,即在反向引用中,在替换模式中以及程序的以下行中引用这些组。

数值指数随着表达式中组的数量或排列的变化而变化,因此相比之下它们更脆弱。

例如,要匹配用单引号或双引号(['"])括起来的单词(\w+),我们可以使用:

(?<quote>['"])\w+\k{quote}

这相当于:

(['"])\w+\1

在这种简单的情况下,常规编号的捕获组没有任何缺点。

在更复杂的情况下,使用命名组将使表达式的结构对读者更明显,这提高了可维护性。

日志文件解析是受益于组名称的更复杂情况的示例。这是 Apache 通用日志格式 (CLF):

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

以下表达式将部件捕获到命名组中:

(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)

语法取决于风格,常见的是:

  • (?<name>...)
  • (?'name'...)
  • (?P<name>...)

反向引用:

  • \k<name>
  • \k{name}
  • \k'name'
  • \g{name}
  • (?P=name)

在 .NET 风格中,你可以拥有多个共享相同名称的组,它们将使用捕获堆栈

在 PCRE 中,你必须使用 (?J) 修饰符(PCRE_DUPNAMES)或使用分支重置组 (?|) 明确启用它。但是只能访问最后捕获的值。

(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))