在Java正则表达式中如何找到匹配的组而不进行线性搜索?

7

我有一些通过编程组装的大型正则表达式,就像这样:

(A)|(B)|(C)|...

每个子模式都在其捕获组中。当我得到一个匹配时,如何找出哪个组匹配,而不是线性测试每个group(i)以查看它是否返回非空字符串?


你想查找匹配哪个组或组的内容? - Ben Lings
我不知道有没有一个正则表达式系统可以做到你所要求的,而且我很确定 Java 核心中的那个是线性系统。请参考 @Thomas 的帖子以获得更好的细节。 - aperkins
5个回答

4
如果您的正则表达式是通过编程生成的,为什么不编程生成n个单独的正则表达式,然后依次测试每个表达式呢?除非它们共享一个公共前缀并且 Java 正则表达式引擎很聪明,否则所有的备选项都会被测试。
更新:我刚刚查看了 Sun Java 源代码,特别是 java.util.regex.Pattern$Branch.match(),它只是简单地对所有备选项进行线性搜索,逐个尝试。在使用 Branch 的其他地方没有任何优化公共前缀的迹象。

是的,它们可能共享前缀等。 - Fortepianissimo

1

дҪ еҸҜд»ҘдҪҝз”ЁйқһжҚ•иҺ·з»„пјҢиҖҢдёҚжҳҜпјҡ

(A)|(B)|(C)|...

жӣҝжҚўдёә

((?:A)|(?:B)|(?:C))

йқһжҚ•иҺ·з»„(?:)е°ҶдёҚдјҡиў«еҢ…жӢ¬еңЁз»„и®Ўж•°дёӯпјҢдҪҶеҲҶж”Ҝзҡ„з»“жһңе°Ҷиў«жҚ•иҺ·еңЁеӨ–йғЁ()з»„дёӯгҖӮ


0

将你的正则表达式分成三部分:

String[] regexes = new String[] { "pattern1", "pattern2", "pattern3" };

for(int i = 0; i < regexes.length; i++) {
  Pattern pattern = Pattern.compile(regexes[i]);

  Matcher matcher = pattern.matcher(inputStr);
  if(matcher.matches()) {
     //process, optionally break out of loop
  }
}

public int getMatchedGroupIndex(Matcher matcher) { 
  int index = -1;  

  for(int i = 0; i < matcher.groupCount(); i++) {
    if(matcher.group(i) != null && matcher.group(i).trim().length() > 0) {
      index = i;
    }
  }

  return index;
}

另一种选择是:

for(int i = 0; i < matcher.groupCount(); i++) {
  if(matcher.group(i) != null && matcher.group(i).trim().length() > 0) {
     //process, optionally break out of loop
  }
}

我不想进行线性搜索。我想知道是否可以获得这个不存在的方法Matcher.getMatchedGroupIndex()的功能,它会神奇地告诉我哪个组匹配,而无需逐个测试每个组。 - Fortepianissimo
我添加了getMatchedGroupIndex()方法,但在底层它仍然使用FOR循环来迭代组内容。 - OMG Ponies

0

我认为你不能避免线性搜索,但是你可以通过使用start(int)而不是group(int)来使其更加高效。

static int getMatchedGroupIndex(Matcher m)
{ 
  int index = -1;
  for (int i = 1, n = m.groupCount(); i <= n; i++)
  {
    if ( (index = m.start(i)) != -1 )
    {
      break;
    }
  }
  return index;
}

这种方式,不需要为每个组生成子字符串,只需查询代表其起始索引的int值。


0
从各种评论中看来,简单的回答是“不行”,使用单独的正则表达式更好。要改进这种方法,您可能需要在生成它们时找出常见的模式前缀,或者使用自己的正则表达式(或其他)模式匹配引擎。但是,在您付出所有这些努力之前,您需要确信这是您系统中的一个重要瓶颈。换句话说,对其进行基准测试,并查看性能是否足以处理现实输入数据,如果不是,则进行分析以确定实际瓶颈在哪里。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接