命名捕获组
一些正则表达式风格允许命名捕获组。你可以在后续代码中按名称引用这些组,而不是通过数字索引引用这些组,即在反向引用中,在替换模式中以及程序的以下行中引用这些组。
数值指数随着表达式中组的数量或排列的变化而变化,因此相比之下它们更脆弱。
例如,要匹配用单引号或双引号(['"]
)括起来的单词(\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>...))