java - 用于提取所有可能金额的正则表达式

标签 java regex

我正在寻找一个正则表达式,它将从字符串中提取所有可能的金额,假设金额始终包含 2 个小数,并接受 ., 自由地作为分隔符。例如,对于以下字符串,我想找到以下金额:

1.234,567.89

1.23
1.234,56
  234,56
   34,56
    4,56
1.234,567.89
  234,567.89
   34,567.89
    4,567.89
      567.89
       67.89
        7.89

这可以用正则表达式实现吗?

我当前的正则表达式是 ?\\d{1,3}([\\.,]\\d{3})*([\\.,]\\d{2}) 但这显然不起作用,因为它只返回 1 个匹配项。

最佳答案

所以,最初,我认为这不能用正则表达式来完成。我的假设是错误的,但这只能通过删除重复项和空字符串/空值来实现。

正则表达式

See regex in use here

(?=(\d+[.,]\d{2}))(?=((?:\d+[.,]){2,}?\d{2})?)(?=((?:\d+[.,])+\d{2}))

上面的模式包含 3 个正面前瞻。它们如下:

  1. (?=(\d+[.,]\d{2})) 确保以下匹配
    • (\d+[.,]\d{2}) 将以下内容捕获到捕获组 1 中。这会捕获较短的变体,例如 1.23
      • \d+匹配一个或多个数字
      • [.,] 按字面匹配 .,
      • \d{2} 正好匹配 2 个数字
  2. (?=((?:\d+[.,]){2,}?\d{2})?) 确保以下匹配
    • ((?:\d+[.,]){2,}?\d{2})? 可选择将以下内容捕获到捕获组 2 中。这会捕获 in-在 数字之间,例如 1.234,56,其中在同一位置存在较小版本和较长版本(分别为 1.231.234,567.89 ).如果可能有更长的数字版本,您可能需要添加更多与此相同的正面前瞻,并将下一节中的 {2,} 更改为 {3,}{4,} 等并将这些组添加到 while 循环中。如果不存在 in-between 数字,它将简单地捕获与第三个 lookahead 相同的数字(代码中删除了重复项)。
      • (?:\d+[.,]){2,}? 匹配以下 2 次或更多次,但尽可能少。
        • \d+匹配一个或多个数字
        • [.,] 按字面匹配 .,
      • \d{2} 正好匹配 2 个数字
  3. (?=((?:\d+[.,])+\d{2})) 确保以下匹配
    • ((?:\d+[.,])+\d{2}) 将以下内容捕获到捕获组 3 中。这会捕获更长的变体,例如 1.234,567.89
      • (?:\d+[.,])+ 匹配以下一次或多次
        • \d+匹配一个或多个数字
        • [.,] 按字面匹配 .,
      • \d{2} 正好匹配 2 个数字

代码

下面的代码简单地遍历所有匹配项并提取组值,将它们添加到 List 中。然后使用找到的方法从列表中删除 nullhere .然后根据 this answer 将该列表变成 Set 以删除重复项。并添加回(现在为空)列表。

See code in use here

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Main{
    public static void main(String[] args) {
        String s = "1.234,567.89";
        Pattern p = Pattern.compile("(?=(\\d+[.,]\\d{2}))(?=((?:\\d+[.,]){2,}?\\d{2})?)(?=((?:\\d+[.,])+\\d{2}))");
        Matcher m = p.matcher(s);

        List<String> al = new ArrayList<>();
        Set<String> hs = new HashSet<>();

        while(m.find()) {
            al.add(m.group(1));
            al.add(m.group(2));
            al.add(m.group(3));
        }

        al.removeAll(Collections.singleton(null));
        hs.addAll(al);
        al.clear();
        al.addAll(hs);

        System.out.println(al);
    }
}

结果

下面结果中的数字与 OP 的值列表一致(尽管输出看起来不同,但您可以通过交叉检查两组值来确认)。

[34,567.89, 4,56, 7.89, 234,56, 4,567.89, 1.234,56, 1.23, 1.234,567.89, 34,56, 567.89, 67.89, 234,567.89]

关于java - 用于提取所有可能金额的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49925964/

相关文章:

java - 如何在没有模型的情况下查找 JSON 中的特定元素

java - Spring boot Mapstruct StackOverFlow错误

ruby - 反斜杠 + Ruby 正则表达式中的捕获组

regex - unicode 上的字捕获失败错误,如何修复 5.10

c++11 (MSVS2012) 正则表达式在多行 std::string 中查找文件名

java - 如何对列表执行与顺序无关的相等性检查?

java - 如何从 Minecraft 编辑 .mca 文件?

java - 使用 Maven 和 Jersey/Jackson 设置生成的依赖于平台的 .war 文件?

JavaScript 正则表达式帮助 : Match 0 or 1 times but do not capture

java - jackson 错误: unacceptable character '' (0x0) special characters are not allowed