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

wvd*_*vdz 4 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
Run Code Online (Sandbox Code Playgroud)

这是用正则表达式实现的吗?

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

ctw*_*els 5

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

正则表达式

请参阅此处使用的正则表达式

(?=(\d+[.,]\d{2}))(?=((?:\d+[.,]){2,}?\d{2})?)(?=((?:\d+[.,])+\d{2}))
Run Code Online (Sandbox Code Playgroud)

上面的模式包含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.这将捕获中间数字,例如1.234,56较小版本和较长版本存在于同一位置(1.231.234,567.89分别).如果再多个版本是可能的,你可能需要添加相同方式分享和改变更积极的向前看符号{2,}在下面的部分{3,},{4,}等等,并添加这些组的while循环.如果不存在中间数字,它将只捕获与第三个前瞻相同的内容(代码中删除了副本).
      • (?:\d+[.,]){2,}? 匹配以下2次或更多次,但尽可能少.
        • \d+ 匹配一个或多个数字
        • [.,]匹配.,字面上
      • \d{2} 正好匹配2位数
  3. (?=((?:\d+[.,])+\d{2})) 确保以下匹配
    • ((?:\d+[.,])+\d{2})将以下内容捕获到捕获组3中.这样可以捕获更长的变体1.234,567.89.
      • (?:\d+[.,])+ 匹配以下一次或多次
        • \d+ 匹配一个或多个数字
        • [.,]匹配.,字面上
      • \d{2} 正好匹配2位数

下面的代码简单地迭代所有匹配并提取组值将它们添加到a List.null然后使用此处找到的方法从列表中删除值.然后Set根据此答案将列表转换为a 以删除重复项,并将其添加回(现在为空)列表.

请参阅此处使用的代码

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

结果

下面结果中的数字与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]
Run Code Online (Sandbox Code Playgroud)