我有一些数字想要应用一些正则表达式替换。
+000123,456
+123
000123,456
123
+123.45
-123,45
我想删除+号(如果存在)并用点替换逗号。 困难的部分是并非所有数字都是小数。
我不经常使用正则表达式,所以我通常使用 regex101 来做一些测试。
在本例中,我创建了以下正则表达式:
([+]*)([0-9]+)(([,])([0-9]+))*
第一捕获组:
([+]*)
([0-9]+)
(([,])([0-9]+))*
([,])
([0-9]+)
和替换:
$2${3:+.$5:}
说明:使用第二个捕获组,然后如果存在第三个捕获组,则使用 DOT 和第五个捕获组,否则什么都没有
并且似乎工作正常,但是尝试在 Java 上复制相同的内容,但它不起作用:
private String replaceUsingRegex(final String line) {
Pattern regex = Pattern.compile("([+]*)([0-9]+)(([,])([0-9]+))*");
Matcher regexMatcher = regex.matcher(line);
return regexMatcher.replaceAll("$2${3:+.$5:}");
}
在第三行给了我一个 IllegalArgumentException:
java.lang.IllegalArgumentException: named capturing group is missing trailing '}'
at java.base/java.util.regex.Matcher.appendExpandedReplacement(Matcher.java:1051)
at java.base/java.util.regex.Matcher.appendReplacement(Matcher.java:997)
at java.base/java.util.regex.Matcher.replaceAll(Matcher.java:1181)
at com.mytest.TestRegex.replaceUsingRegex(TestRegex.java:20)
我也尝试使用由reg101生成的java代码,但仍然无法工作。
“...第三行出现 IllegalArgumentException ...”
您收到此错误的原因是 Java 正则表达式实现无法识别
$2${3:+.$5:}
的“条件”替换语法。${ }
构造预计仅包含对捕获组的文字引用。
例如,
(?<name>abc)
和${name}
。
我相信您使用的语法特定于 perl、PCRE 实现。
Perldoc – perlre – Perl 正则表达式。
Perldoc – perlretut – Perl 正则表达式教程。
这里是 Pattern 和 Matcher 类的 JavaDocs。
您可以在 Pattern JavaDoc 页面上找到完整的语法规范。
模式(Java SE 20 和 JDK 20)。
匹配器(Java SE 20 和 JDK 20)。
并且,相关摘录, Matcher#appendReplacement(Java SE 20 和 JDK 20)。
"... 替换字符串可能包含对上一个匹配期间捕获的子序列的引用:每次出现 ${name} 或 $g 将分别替换为相应 group(name) 或 group(g) 的计算结果.对于 $g,$ 之后的第一个数字始终被视为组引用的一部分。如果后续数字可以形成合法的组引用,则将其合并到 g 中。只有数字“0”到“9”被视为潜在的数字组参考的组成部分。...”
您可以执行一些操作来解析这些值。
“...我想删除+号(如果存在)并用点替换逗号。困难的部分是并非所有数字都是小数。...”
如果值只有 1 个逗号和一个可能的 + 字符,则可以仅使用 String#replace 调用。
String[] strings = {
"+000123,456",
"+123",
"000123,456",
"123",
"+123.45",
"-123,45"
};
for (String string : strings) {
string = string.replace("+", "").replace(",", ".");
System.out.println(string);
}
输出
000123.456
123
000123.456
123
123.45
-123.45
当然,当数字位于还包含不相关的逗号和加号的文本中时,这还不够。
为此,您可以使用 Pattern 和 Matcher 类来捕获值,然后将它们附加到新的 StringBuilder 实例。
图案将是,
\+?(-?\d+)(?:[,.](\d+))?
String string = "abc, +000123,456 def +123, ghi 000123,456 jkl, 123 mno +123.45, pqr -123,45";
Pattern pattern = Pattern.compile("\\+?(-?\\d+)(?:[,.](\\d+))?");
Matcher matcher = pattern.matcher(string);
StringBuilder stringB = new StringBuilder();
int offset = 0;
while (matcher.find()) {
stringB.append(string, offset, matcher.start());
stringB.append(matcher.group(1));
if (matcher.group(2) != null) stringB.append(".").append(matcher.group(2));
offset = matcher.end();
}
输出
abc, 000123.456 def 123, ghi 000123.456 jkl, 123 mno 123.45, pqr -123.45
在我看来,正则表达式对此来说太过分了。首先,只需替换加号,然后替换逗号。
String[] values = {
"+000123,456","+123","000123,456","123","+123.45","-123,45"
};
for (String value : values) {
String s = value.replace("+", "").replace(",", ".");
System.out.println(s);
}
打印
000123.456
123
000123.456
123
123.45
-123.45
您也可以编写一个 lambda 来完成此操作。
UnaryOperator<String> convert = str->str.replace("+", "").replace(",", ".");
String result = convert.apply("+1202,233");
System.out.println(result);
打印
1202.233
private static String replaceUsingRegex(final String line) {
Pattern regex = Pattern.compile("(\\+?)(0*)([0-9]+)([,\\.])?([0-9]+)?");
Matcher regexMatcher = regex.matcher(line);
if (regexMatcher.find()) {
String result = regexMatcher.group(3).replaceFirst("^0+", "");
if (regexMatcher.group(4) != null && regexMatcher.group(5) != null) {
result += "." + regexMatcher.group(5);
}
return result;
}
return line;
}
第一个捕获组:
(\\+?)
- 前导“+”号 (0*)
- 零大于 1 ([0-9]+)
- 点/逗号之前的所有数字 ([,\\.]?)
- 逗号和点,可选 ([0-9]+)?
- 分隔符后的数字