pol*_*nts 4 java regex capturing-group
假设我们有以下输入:
<amy>
(bob)
<carol)
(dean>
Run Code Online (Sandbox Code Playgroud)
我们还有以下正则表达式:
<(\w+)>|\((\w+)\)
Run Code Online (Sandbox Code Playgroud)
现在我们得到两场比赛(如rubular.com上所示):
<amy>是匹配,\1捕获amy,\2失败(bob)是匹配,\2捕获bob,\1失败这个正则表达式完成了我们想要的大部分内容,它们是:
但是,它确实有一些缺点:
\w+在这种情况下,但一般来说这可能非常复杂,
\1或\2在这种情况下,但通常"主要"部分可以拥有自己的捕获组!{...},情况会迅速恶化[...].所以问题很明显:如何在不重复"主要"模式的情况下做到这一点?
注意:在很大程度上我对
java.util.regex口味感兴趣,但欢迎其他口味.
这部分没有什么新内容; 它只用一个例子说明了上面提到的问题.
让我们将上面的例子带到下一步:我们现在想要匹配这些:
<amy=amy>
(bob=bob)
[carol=carol]
Run Code Online (Sandbox Code Playgroud)
但不是这些:
<amy=amy) # non-matching bracket
<amy=bob> # left hand side not equal to right hand side
Run Code Online (Sandbox Code Playgroud)
使用替代技术,我们有以下工作(如rubular.com上所示):
<((\w+)=\2)>|\(((\w+)=\4)\)|\[((\w+)=\6)\]
Run Code Online (Sandbox Code Playgroud)
如上所述:
\1 \2,\3 \4或\5 \6在进行真正的匹配之前,您可以使用前瞻"锁定"组号.
String s = "<amy=amy>(bob=bob)[carol=carol]";
Pattern p = Pattern.compile(
"(?=[<(\\[]((\\w+)=\\2))(?:<\\1>|\\(\\1\\)|\\[\\1\\])");
Matcher m = p.matcher(s);
while(m.find())
{
System.out.printf("found %s in %s%n", m.group(2), m.group());
}
Run Code Online (Sandbox Code Playgroud)
输出:
found amy in <amy=amy>
found bob in (bob=bob)
found carol in [carol=carol]
Run Code Online (Sandbox Code Playgroud)
它仍然很难看,但每次进行更改时都不必重新计算所有组号.例如,要添加对大括号的支持,它只是:
"(?=[<(\\[{]((\\w+)=\\2))(?:<\\1>|\\(\\1\\)|\\[\\1\\]|\\{\\1\\})"
Run Code Online (Sandbox Code Playgroud)