2014-03-07 65 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(); 
     } 

    } 
}