2014-01-22 60 views
5

我知道/?意味着/是可選的。那麼「玩具?」將匹配玩具和玩具。我的理解是,如果我懶得使用「玩具??」我會匹配玩具和玩具,並始終返回玩具。因此,快速測試:Java正則表達式兩個問號(??)

private final static Pattern TEST_PATTERN = Pattern.compile("toys??", Pattern.CASE_INSENSITIVE); 
public static void main(String[] args) { 
    for(String arg : args) { 
     Matcher m = TEST_PATTERN.matcher(arg); 
     System.out.print("Arg: " + arg); 
     boolean b = false; 
     while (m.find()) { 
      System.out.print(" {"); 
      for (int i=0; i<=m.groupCount(); ++i) { 
       System.out.print("[" + m.group(i) + "]"); 
      } 
      System.out.print("}"); 
     } 
     System.out.println(); 
    } 
} 

是的,它看起來像它按預期工作

java -cp .. regextest.RegExTest toy toys 
Arg: toy {[toy]} 
Arg: toys {[toy]} 

現在,改變正則表達式「玩具?2」,它仍然匹配toys2和toy2。在這兩種情況下,它都會返回整個字符串,而不會刪除。搜索「玩具?2」和「玩具?? 2」有什麼功能上的區別。

我要求的原因是因爲我發現等的例子如下:

private final static Pattern TEST_PATTERN = Pattern.compile("</??tag(\\s+?.*?)??>", Pattern.CASE_INSENSITIVE); 

,雖然我看到使用沒有明顯的原因??而不是?,我認爲也許原來的作者(誰不知道我)可能知道我沒有的東西,我期待着後者。

+0

@remus:它在Java中有效 – nhahtdh

+0

爲什麼它不應該是有效的?這是對'?'的一個懶惰修改。 – raina77ow

+0

@nhahtdh奇怪,我從來沒有聽說過這樣的事情。鏈接? – brandonscript

回答

14

??是懶,而?是貪婪。

鑑於(pattern)??,它將首先測試空字符串,然後如果模式的其餘部分不匹配,它將測試pattern

相比之下,(pattern)?首先會測試pattern,然後它會測試返回的空字符串。


現在,正則表達式更改爲 「玩具?2」,它仍然匹配toys2和toy2。在這兩種情況下,它都會返回整個字符串,而不會刪除。搜索「玩具?2」和「玩具?? 2」有什麼功能上的區別。

的區別在於搜索的順序:爲toys2

  • "toys?2"搜索,然後toy2
  • "toys??2"搜索toy2,然後toys2

但對於這些情況2模式,結果將是相同的,無論輸入字符串,因爲後續2(在s?s??之後)必須匹配。


至於圖案,你發現:

Pattern.compile("</??tag(\\s+?.*?)??>", Pattern.CASE_INSENSITIVE) 

兩個??可以更改爲?而不影響結果:

  • /t(在tag)的互斥。你或者匹配其中一個。
  • >\s也是互斥。在\s+?中至少有1個對於這個結論很重要:否則結果可能會不同。

這可能是作者的微觀優化。他可能認爲開放標籤必須在那裏,而結束標籤可能會被遺忘,並且沒有屬性/隨機空間的開放/關閉標籤比那些有標籤的開放/關閉標籤更常出現。

順便說一句,當輸入了隨後大量的空間<tag沒有>任何接近的引擎可能會碰到一些昂貴的回溯嘗試由於\\s+?.*?

+0

謝謝....所以它不影響答案,只是基於預期輸入的效率。 – Andrew