簡體   English   中英

找出哪些組匹配Java正則表達式而不進行線性搜索?

[英]Find out which group matches in Java regex without linear search?

我有一些以編程方式組裝的巨大正則表達式,就像這樣

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

每個子模式都在其捕獲組中。 當我得到匹配時,如何在不對每個group(i)進行線性測試的情況下確定哪個組匹配group(i)看它返回非空字符串?

如果以編程方式生成正則表達式,為什么不以編程方式生成n個單獨的正則表達式並依次測試它們中的每一個? 除非它們共享一個共同的前綴並且Java正則表達式引擎很聰明,否則所有替代方案都會得到測試。

更新:我只是查看了Sun Java源代碼,特別是java.util.regex.Pattern $ Branch.match(),這也簡單地對所有備選方案進行線性搜索,依次嘗試每個備選方案。 使用Branch的其他地方不建議對公共前綴進行任何類型的優化。

您可以使用非捕獲組,而不是:

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

用。。。來代替

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

非捕獲組(?:)不會包含在組計數中,但分支的結果將在outer()組中捕獲。

將你的正則表達分為三個:

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
  }
}

我認為你不能繞過線性搜索,但是你可以通過使用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值,而不是為每個組生成子字符串。

從各種評論來看,似乎簡單的答案是“不”,並且使用單獨的正則表達式是一個更好的主意。 要改進該方法,您可能需要在生成它們時找出常見的模式前綴,或者使用您自己的正則表達式(或其他)模式匹配引擎。 但在您完成所有這些工作之前, 您需要確保這是您系統中的一個重要瓶頸。 換句話說,對它進行基准測試,看看性能是否可以接受真實的輸入數據,如果不是配置文件,則可以看到真正的瓶頸所在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM