Java 上的正则表达式条件替换

问题描述 投票:0回答:3

我有一些数字想要应用一些正则表达式替换。

+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代码,但仍然无法工作。

java regex regex-group
3个回答
3
投票

“...第三行出现 IllegalArgumentException ...”

您收到此错误的原因是 Java 正则表达式实现无法识别

$2${3:+.$5:}
的“条件”替换语法。
${ }
构造预计仅包含对捕获组的文字引用。

例如,

(?<name>abc)
${name}

我相信您使用的语法特定于 perlPCRE 实现。
Perldoc – perlre – Perl 正则表达式
Perldoc – perlretut – Perl 正则表达式教程

这里是 PatternMatcher 类的 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

当然,当数字位于还包含不相关的逗号和加号的文本中时,这还不够。

为此,您可以使用 PatternMatcher 类来捕获值,然后将它们附加到新的 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

3
投票

在我看来,正则表达式对此来说太过分了。首先,只需替换加号,然后替换逗号。

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

0
投票
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]+)
- 点/逗号之前的所有数字
第四个捕获组:
([,\\.]?)
- 逗号和点,可选
第 5 个捕获组:
([0-9]+)?
- 分隔符后的数字

© www.soinside.com 2019 - 2024. All rights reserved.