java - 使用同一组捕获 <thisPartOnly> 和 (thisPartOnly)

标签 java regex capturing-group

假设我们有以下输入:

<amy>
(bob)
<carol)
(dean>

我们还有以下正则表达式:

<(\w+)>|\((\w+)\)

现在我们得到两个匹配项 ( as seen on rubular.com ):

  • <amy>是一场比赛,\1捕获 amy , \2失败
  • (bob)是一场比赛,\2捕获 bob , \1失败

这个正则表达式完成了大部分我们想要的,它们是:

  • 正确匹配左括号和右括号(即不混合)
  • 它捕获了我们感兴趣的部分

但是,它也有一些缺点:

  • 重复捕获模式(即“主要”部分)
    • 只有\w+在这种情况下,但一般来说,这可能非常复杂,
      • 如果涉及反向引用,则必须为每个替代项重新编号!
      • 重复使维护成为噩梦! (如果它改变了怎么办?)
  • 这些组基本上是重复的
    • 根据备用匹配项,我们必须查询不同的组
      • 只有\1\2在这种情况下,但通常“主要”部分可以有自己的捕获组!
    • 这不仅不方便,而且可能存在不可行的情况(例如,当我们使用仅限于查询一组的自定义正则表达式框架时)
  • 如果我们还想匹配{...},情况会迅速恶化, [...]

所以问题很明显:我们如何在不重复“主要”模式的情况下做到这一点?

Note: for the most part I'm interested in java.util.regex flavor, but other flavors are welcomed.


附录

本节没有新内容;仅举例说明上述问题。

让我们把上面的例子带到下一步:我们现在要匹配这些:

<amy=amy>
(bob=bob)
[carol=carol]

但不是这些:

<amy=amy)   # non-matching bracket
<amy=bob>   # left hand side not equal to right hand side

使用替代技术,我们可以使用以下方法 ( as seen on rubular.com ):

<((\w+)=\2)>|\(((\w+)=\4)\)|\[((\w+)=\6)\]

如上所述:

  • 不能简单地重复主要模式;反向引用必须重新编号
  • 如果发生变化,重复也意味着维护噩梦
  • 根据备用匹配项,我们必须查询 \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());
}

输出:

found amy in <amy=amy>
found bob in (bob=bob)
found carol in [carol=carol]

它仍然非常丑陋,但您不必每次进行更改时都重新计算所有组号。例如,要添加对大括号的支持,只需:

"(?=[<(\\[{]((\\w+)=\\2))(?:<\\1>|\\(\\1\\)|\\[\\1\\]|\\{\\1\\})"

关于java - 使用同一组捕获 <thisPartOnly> 和 (thisPartOnly),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3165755/

相关文章:

Java:小程序有哪些可用的安全设置

java - Java 正则表达式中 matches() 和 find() 之间的区别

python - 如何提取用引号括起来的元素列表,以 <> 为界并以逗号分隔 - python,正则表达式?

Python:正则表达式:使用一个正则表达式检测连字符的名称和非连字符的名称

regex - 正则表达式中的非捕获组是什么?

regex - 如何重新使用捕获组来匹配不同的交替选择?

java - Jsoup 在标记后选择文本

java - 为什么 stroke() 的 alpha 参数导致不绘制任何内容?

java - 亚马逊 mws 能够注意到受限产品

java - java中如何实现正则表达式替换功能?