我试图匹配大部分数字,但根据表达式后面的单词,我需要做出改变。
我匹配每个后面没有温度术语(例如°C)或时间规范的数字。 我的正则表达式如下所示:
(((\d+?)(\s*)(\-)(\s*))?(\d+)(\s*))++(?!minuten|Minuten|min|Min|Stunden|stunden|std|Std|°C| °C)
这是一个示例:http://regexr.com?33jeg
虽然这种行为是我所期望的,但 Java 会执行以下操作: Index是第4场比赛对应的Group
0: "4 "1: "4 "2: "0 - "3: "0"4: " "5: "-"6: " "7: "4"8: " "9: "°C"
您需要知道我单独匹配每个字符串。所以 5 的匹配看起来像这样:
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());
}
}
希望你能告诉我我错过了什么。
最佳答案
这似乎是 Java 实现中的一个错误(或功能?)。当必须从下一个索引重做匹配时,它似乎不会重置捕获组的捕获文本。
此测试揭示了 Java 正则表达式引擎和 PHP 的 PCRE 之间的行为差异。
- 正则表达式:
(\d+(-\d+)?){1}+(?!x)
- 输入:
34 34-43x 78 90
- Java 结果:3 个匹配项(
34
、78
、90
)。第二场比赛的第二个捕获组是-43
。第二个捕获组在第 1 场和第 3 场比赛中没有捕获任何内容。 - PHP result :也是相同的 3 场比赛,但第二个捕获组没有捕获所有比赛的任何内容。对于 PHP 的 PCRE 实现,当必须重做匹配时,捕获组的捕获文本将被重置。
已在 JRE 6 Update 37 和 JRE 7 Update 11 上进行了测试。
同样的结果,只是为了证明当必须重做匹配时捕获的文本不会重置:
- 正则表达式:
a(\d+(-\d+)?){1}+(?!x)
- 输入:
a34 a34-43x a78 a90
- PHP result
关于您的正则表达式的一些评论
我认为++
应该是{1}+
,因为你似乎想一次修改一个数字或一个数字范围,同时使匹配所有格以丢弃不需要的数字。
解决方法
第一组(最外层的捕获组)捕获所有内容(一个数字或一系列数字),在找到匹配项时将始终被覆盖。因此您可以信赖它。您可以检查组1中是否存在-
(使用contains
方法)。如果有,则可以判断捕获组 2 包含当前匹配中捕获的文本,并且您可以使用捕获的文本。如果没有,那么您可以忽略捕获组 2 及其嵌套捕获组中的所有捕获文本。
关于java - Java 中的正则表达式。意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14602518/