我想检查文件的每一行是否与多个正则表达式模式匹配。
示例: 测试我的文本文件的这一行
123;456;789
针对3种不同的表达方式
1.*;.*;..9
3.*;.*;787
.2.;.*;..9
,并在每个模式匹配或不匹配时执行某些操作。
所以我需要知道我所有模式中的哪一个与否
在这个例子中:
只有P1和P3匹配,所以我对输入123;456;789
嵌套有for循环的幼稚解决方案的性能较差(由于该算法)。
示例:
for(String row : rows){
for (Pattern p : patterns){
if(p.matcher(value).matches()){
//
}
}
}
我当时正在考虑在多个正则表达式中插入“ |”运算符
使用上面的示例:(1.*;.*;..9)|(3.*;.*;787)|(.2.;.*;..9)
String expression = "(1.*;.*;..9)|(3.*;.*;787)|(.2.;.*;..9)";
String value = "123;456;789";
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(value);
HashMap<Integer,Boolean> results= new HashMap<>();
if(matcher.matches()) {
int count = matcher.groupCount();
for (int i = 1; i <= count; ++i) {
results.put(i, matcher.group(i) != null);
}
}
但是引擎会在第一个匹配替代项处停止
是否有一种方法可以在一个呼叫中测试多个不同的模式? 在其他情况下,我该如何改进算法而又不求二次
答案 0 :(得分:1)
这是正则表达式引擎在发现成功匹配项时停止的正确行为。要模拟您要尝试执行的操作,您应该先行工作,但要以某种方式使它们不会中断比赛(很快失败或很快成功)。因此,类似以下正则表达式的东西将尝试匹配三个不同的捕获组。如果捕获组中的一个正则表达式无法匹配(由于它是可选的),则尝试另一前瞻,直到结束:
^(?=(1.*;.*;..9$)?)(?=(3.*;.*;787$)?)(?=(.2.;.*;..9$)?)
如果只捕获了一个组,则只需要稍后使用捕获组来执行一些代码:
if (capturingGroup == 1) {
// do something
} else if (capturingGroup == 2) {
...
请参见live demo here(在这里,您的两个正则表达式是匹配的并且可以识别)
注意:您可能希望删除点星,以使用更具限制性的样式。目前,它的匹配程度很高。
注意:由于此处的两个正则表达式不会同时匹配,因此您可以将上述正则表达式更改为:
^(?:(?=(1.*;.*;..9$)?)(?=(.2.;.*;..9$)?)|(3.*;.*;787)$)
答案 1 :(得分:0)
第一次匹配后,引擎停止,因为第一个模式消耗了输入字符串,而下一个没有任何匹配的输入。您可以在此处使用非消耗性正向预测(?=)
,使整个表达式一目了然
(?=(1.*;.*;..9))(3.*;.*;787)|(.2.;.*;..9)
上面是一个示例情况,它将与第一个表达式匹配,但不会为输入String消耗任何字符,因此下一个regex模式(here (3.*;.*;787))
将整个输入字符串作为输入。您可以使用此概念来创建所需的正则表达式模式