Java中的正则表达式。意外行为

Java中的正则表达式。意外行为,java,regex,parsing,matcher,Java,Regex,Parsing,Matcher,我试图匹配大部分数字,但根据表达式后面的单词,我需要做出改变 我匹配每个数字,这些数字后面没有温度项,如°C或时间规格。 我的正则表达式如下所示: (((\d+?)(\s*)(\-)(\s*))?(\d+)(\s*))++(?!minuten|Minuten|min|Min|Stunden|stunden|std|Std|°C| °C) 0: "5 "1: "5 "2: "null"3: "null"4: &quo

我试图匹配大部分数字,但根据表达式后面的单词,我需要做出改变

我匹配每个数字,这些数字后面没有温度项,如°C或时间规格。 我的正则表达式如下所示:

(((\d+?)(\s*)(\-)(\s*))?(\d+)(\s*))++(?!minuten|Minuten|min|Min|Stunden|stunden|std|Std|°C| °C)
0: "5 "1: "5 "2: "null"3: "null"4: "null"5: "null"6: "null"7: "5"8: " "9: "null"
以下是一个例子:

虽然这种行为正是我所期望的,但Java会执行以下操作: 索引是匹配4的对应组

0: "4 "1: "4 "2: "0 - "3: "0"4: " "5: "-"6: " "7: "4"8: " "9: "°C"
你需要知道我把每个字符串分开匹配。因此,5的匹配如下所示:

(((\d+?)(\s*)(\-)(\s*))?(\d+)(\s*))++(?!minuten|Minuten|min|Min|Stunden|stunden|std|Std|°C| °C)
0: "5 "1: "5 "2: "null"3: "null"4: "null"5: "null"6: "null"7: "5"8: " "9: "null"
我希望另一场比赛是这样的。这种令人不快的行为只有在匹配前字符串中的某个位置出现“-”时才会出现

我的Java代码如下所示:

public static void adaptPortionDetails(EList<Step> steps, double multiplicator){
    
    String portionMatcher = "(((\\d+?)(\\s*)(\\-)(\\s*))?(\\d+)(\\s*))++(?!°C|Grad|minuten|Minuten|min|Min|Stunden|stunden|std|Std)";
    
    for (int i = 0; i < steps.size(); i++) {
        Matcher matcher = Pattern.compile(portionMatcher).matcher(
                steps.get(i).getDescription());
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            printGroups(matcher);
            String newValue1Str;
            if (matcher.group(3) == null){
                newValue1Str = "";
                System.out.println("test");
            }else{
                double newValue1 = Integer.parseInt(matcher.group(3)) * multiplicator;
                newValue1Str = Fraction.getFraction(newValue1).toProperString();
            }
            double newValue2 = Integer.parseInt(matcher.group(7)) * multiplicator;
            String newValue2Str = Fraction.getFraction(newValue2).toProperString();
            
            
            matcher.appendReplacement(sb, newValue1Str + "$4$5$6" + newValue2Str + "$8");
        }
        matcher.appendTail(sb);
        steps.get(i).setDescription(sb.toString());
    }
}
publicstaticvoidadaptportiondetails(eliststeps,双乘法器){
String portionMatcher=“(((\\d+?)(\\s*)(\\-)(\\s*))(\\d+(\\s*))++(?!°C | Grad | minuten | min | min | studen | std | std)”;
对于(int i=0;i
希望你能说出我遗漏了什么。

这似乎是Java实现中的一个bug(或功能?)。当必须从下一个索引重新进行匹配时,它似乎不会为捕获组重置捕获的文本

这个测试揭示了Java正则表达式引擎和PHP的PCRE之间的行为差异

  • 正则表达式:
    (\d+(\d+){1}+(?!x)
  • 输入:
    3434-43x7890
  • Java结果:3个匹配(
    34
    78
    90
    )。第二场比赛的第二个捕获组是
    -43
    。第二个捕获组在第一场和第三场比赛中没有捕获任何内容
  • :也是相同的3个匹配项,但第2个捕获组对所有匹配项均不捕获任何内容。对于PHP的PCRE实现,当必须重新进行匹配时,将重置捕获组的捕获文本
这在JRE 6更新37和JRE 7更新11上进行了测试

同样的结果,只是为了证明在必须重新进行匹配时捕获的文本不会重置:

  • 正则表达式:
    a(\d+(\d+){1}+(?!x)
  • 输入:
    a34 a34-43x a78 a90
一些关于您的正则表达式的评论

我认为
++
应该是
{1}++
,因为您似乎希望一次修改一个数字或一个数字范围,同时使匹配具有所有格以丢弃不需要的数字

解决方法


第一个组(最外层的捕获组)捕获所有内容(一个数字或一系列数字),在找到匹配项时将始终被覆盖。因此你可以信赖它。您可以检查组1中是否存在
-
(使用
包含
方法)。如果有,则可以判断捕获组2包含来自当前匹配的捕获文本,并且可以使用捕获文本。如果没有,那么您可以忽略捕获组2及其嵌套捕获组中的所有捕获文本。

不愉快的行为到底是什么?您能更清楚地描述它吗?您是否需要那么多的捕获组
()
?因为组2到7应该为空。但在第3组中,例如字符串“0”,它是初始字符串190的最后一位。即使整场比赛是我想要的。我真的不需要所有的团体。但是我需要得到第3组和第7组,我需要用它们计算一些东西,然后把计算出的值放在指定的位置position@lugges:为什么单独放置的正则表达式与代码中的正则表达式不同?这是因为在我的原始代码中,我从不同的数组构建正则表达式,并使用print方法将其放在这里作为常数。我在最初的帖子和代码中删除了围绕°C的圆括号。还有什么我不知道的吗?谢谢。很高兴知道我理解正确,而且这种行为不符合逻辑。你对我有什么建议吗?怎样才能得到一个更适合我情况的结果