【问题标题】:Regex for extracting all possible amounts用于提取所有可能数量的正则表达式
【发布时间】:2018-09-30 05:53:44
【问题描述】:

我正在寻找一个正则表达式,它将从字符串中提取所有可能的金额,假设金额始终包含 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 个匹配项。

【问题讨论】:

  • 一个字符一旦出现在一场比赛中,就不能在另一场比赛中重复使用。
  • 只是好奇,它的目的是什么?
  • @4castle 不完全正确,它可以通过Backreference,虽然我同意,但不适用于这种情况

标签: java regex


【解决方案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。这将捕获 中间 数字,例如 1.234,56,其中较小版本和较长版本存在于同一位置(1.231.234,567.89分别)。如果可能有更长的数字版本,您可能需要添加更多与此相同的正向预测,并将下一节中的{2,} 更改为{3,}{4,} 等,并将这些组添加到while 循环中。如果不存在 in-between 数字,它将简单地捕获与第三次前瞻相同的内容(代码中删除了重复项)。
      • (?:\d+[.,]){2,}? 匹配以下 2 次或更多次,但越少越好。
        • \d+ 匹配一位或多位数字
        • [.,] 匹配 ., 字面意思
      • \d{2} 精确匹配 2 位数字
  3. (?=((?:\d+[.,])+\d{2})) 确保以下匹配
    • ((?:\d+[.,])+\d{2}) 将以下内容捕获到捕获组 3。这将捕获更长的变体,例如 1.234,567.89
      • (?:\d+[.,])+ 匹配以下1次或多次
        • \d+ 匹配一位或多位数字
        • [.,] 匹配 ., 字面意思
      • \d{2} 精确匹配 2 位数字

代码

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

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]

【讨论】:

  • 太棒了。等待解释:)
  • 确实很棒:D Thx
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-23
相关资源
最近更新 更多