2014-03-07 61 views
13

我有一個輸入字符串。將字符串與多個正則表達式匹配

我想如何有效地將這個字符串與多個正則表達式進行匹配。

Example Input: ABCD 

我想對陣這些REG-EX模式,並返回true如果其中至少有一個匹配:

[a-zA-Z]{3} 

^[^\\d].* 

([\\w&&[^b]])* 

我不知道如何來匹配多個模式一次。有人能告訴我我們如何有效地做到這一點?

+2

你的問題不清楚(至少對我而言)。有效的意思是什麼?你想檢查輸入是否匹配所有正則表達式,或者只有一個是足夠的?你可以在輸入期望的輸出旁包含嗎? – Pshemo

+1

我認爲,首先,你應該用自然語言來定義你想要匹配的字符序列。你的例子不讓我們提取任何模式。或者,最好的是,這裏的模式最符合您的輸入:「ABCD」。 –

+0

你想實現什麼? – wumpz

回答

19

如果您只有幾個正則表達式,它們都是已知的在編譯的時候,這就足夠了:

private static final Pattern 
    rx1 = Pattern.compile("..."), 
    rx2 = Pattern.compile("..."), 
    ...; 

return rx1.matcher(s).matches() || rx2.matcher(s).matches() || ...; 

如果有更多的,或者他們被加載在運行時,然後使用一組模式:

final List<Pattern> rxs = new ArrayList<>(); 


for (Pattern rx : rxs) if (rx.matcher(input).matches()) return true; 
return false; 
+0

完整的文檔在這裏:https://dzone.com/refcardz/regular-expressions – Benj

+5

什麼是最有效的方法:多個匹配器或多個模式通過管道連接? – Benj

1

我不知道什麼effectively手段,但如果它是關於性能,你想查了很多串,我會去爲這個

... 
static Pattern p1 = Pattern.compile("[a-zA-Z]{3}"); 
static Pattern p2 = Pattern.compile("^[^\\d].*"); 
static Pattern p3 = Pattern.compile("([\\w&&[^b]])*"); 

public static boolean test(String s){ 
    return p1.matcher(s).matches ? true: 
     p2.matcher(s).matches ? true: 
     p3.matcher(s).matches; 
} 

我不知道它將如何影響性能,但將它們與|合併成一個正則表達式也可能有所幫助。

+0

這重新邏輯or或缺少括號。爲什麼不使用'p1.matcher(s).matches()|| p2.matcher(s).matches()|| p3.matcher(s).matches()' – kratenko

+0

你是對的。我不知道4年前我在想什麼。 – NeplatnyUdaj

1

爲了避免重新創建Pattern和Matcher類的實例,您可以創建其中的一個並重用它們。要重用Matcher課程,您可以使用reset(newInput)方法。 警告:此方法不是線程安全的。只有當你能保證只有一個線程能夠使用這個方法時才使用它,否則爲每個方法調用創建一個單獨的Matcher實例。

這是可能的代碼示例

private static Matcher m1 = Pattern.compile("regex1").matcher(""); 
private static Matcher m2 = Pattern.compile("regex2").matcher(""); 
private static Matcher m3 = Pattern.compile("regex3").matcher(""); 

public boolean matchesAtLeastOneRegex(String input) { 
    return  m1.reset(input).matches() 
      || m2.reset(input).matches() 
      || m3.reset(input).matches(); 
} 
+1

「Matcher」存在的全部目的是每次創建它以保持單個匹配動作的狀態。你的代碼不是線程安全的。 –

+0

@MarkoTopolnik確實。感謝您指出了這一點。在一個線程環境中,重置Matcher似乎沒有什麼比重新創建它快,所以決定在我的答案中提到它。希望我的編輯能讓我的回答更好。 – Pshemo

18

可以使一個大的正則表達式了個別之一:

[a-zA-Z]{3}|^[^\\d].*|([\\w&&[^b]])* 
+1

@MarkoTopolnik感謝您的更正,不確定關於|所以我已經將它包裹在包裹中以保證安全 – vandale

+2

由於包件也意味着羣組捕獲,因此應該小心對待它們。 –

+0

但是,有沒有什麼辦法來知道我的正則表達式實際上匹配哪一個?我明白,這可能不是@帕坦的目標,但我需要類似的東西。 – Sap

0

這是一個替代方案。 請注意,這不做的一件事是按特定順序返回它們。但是可以通過以m.start()進行排序來實現。

private static HashMap<String, String> regs = new HashMap<String, String>(); 

...

regs.put("COMMA", ","); 
    regs.put("ID", "[a-z][a-zA-Z0-9]*"); 
    regs.put("SEMI", ";"); 
    regs.put("GETS", ":="); 
    regs.put("DOT", "\\."); 

    for (HashMap.Entry<String, String> entry : regs.entrySet()) { 
     String key = entry.getKey(); 
     String value = entry.getValue(); 
     Matcher m = Pattern.compile(value).matcher("program var a, b, c; begin a := 0; end."); 
     boolean f = m.find(); 
     while(f) 
     { 
      System.out.println(key); 
      System.out.print(m.group() + " "); 
      System.out.print(m.start() + " "); 
      System.out.println(m.end()); 
      f = m.find(); 
     } 

    } 
}