正则表达式非贪婪交替

时间:2019-04-03 10:28:29

标签: java regex

我想检查文件的每一行是否与多个正则表达式模式匹配。

示例: 测试我的文本文件的这一行

123;456;789

针对3种不同的表达方式

1.*;.*;..9
3.*;.*;787
.2.;.*;..9

,并在每个模式匹配或不匹配时执行某些操作。 所以我需要知道我所有模式中的哪一个与否 在这个例子中: 只有P1和P3匹配,所以我对输入123;456;789

执行操作1和操作3

嵌套有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);
    }
}

但是引擎会在第一个匹配替代项处停止

是否有一种方法可以在一个呼叫中测试多个不同的模式? 在其他情况下,我该如何改进算法而又不求二次

2 个答案:

答案 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))将整个输入字符串作为输入。您可以使用此概念来创建所需的正则表达式模式