2

I'm looking for are regex for parsing money amounts. The String s10 should not match. Can someone help, or can someone simplify the regex? That's my try:

    public static String[] getMoney(String s) {
        List<String> ret = new ArrayList<String>();
        String regex = "((\\d{1,3}[.,]?)(\\d{3}[.,]?)*[.,]\\d{1,2})(\\D|$)";
        Pattern pat = Pattern.compile(regex);
        Matcher mat = pat.matcher(s);
        while (mat.find()) {
            ret.add(mat.group(1));
        }
        return ret.toArray(new String[0]);
    }

    public static void main(String[] args) {
        String s1 = "0,1"; // should match
        String s2 = ",1"; // should not match
        String s3 = "1,"; // should not match
        String s4 = "1.234,01"; // should match
        String s5 = "1234,10"; // should match
        String s6 = "1234,100"; // should not match
        String s7 = "1234,10a"; // should match
        String s8 = "123,456,789.10"; // should match
        String s9 = "123.456.789,10"; // should match
        String s10 = "123,456.789,10"; // should not match (!)

        System.out.println(Arrays.toString(getMoney(s1)));
        System.out.println(Arrays.toString(getMoney(s2)));
        System.out.println(Arrays.toString(getMoney(s3)));
        System.out.println(Arrays.toString(getMoney(s4)));
        System.out.println(Arrays.toString(getMoney(s5)));
        System.out.println(Arrays.toString(getMoney(s6)));
        System.out.println(Arrays.toString(getMoney(s7)));
        System.out.println(Arrays.toString(getMoney(s8)));
        System.out.println(Arrays.toString(getMoney(s9)));
        System.out.println(Arrays.toString(getMoney(s10)));
    }
unknown_dcba
  • 135
  • 5

1 Answers1

1

I think you may use

(?<![\d,.])(?:\d{1,3}(?:(?=([.,]))(?:\1\d{3})*)?|\d+)(?:(?!\1)[.,]\d{1,2})?(?![,.\d])

See the regex demo

Details

  • (?<![\d,.]) - no digit, . or , allowed immediately on the left
  • (?:\d{1,3}(?:(?=([.,]))(?:\1\d{3})*)?|\d+) -
    • \d{1,3}(?:(?=([.,]))(?:\1\d{3})*)? - one, two or three digits followed with an optional occurrence of a position followed with a comma or dot followed with 0 or more occurrences of the captured value and then any three digits
    • |\d+ - or 1 or more digits
  • (?:(?!\1)[.,]\d{1,2})? - an optional sequence of a comma or dot, but not the same char as in Group 1, and then 1 or 2 digits
  • (?![,.\d]) - no digit, . or , allowed immediately on the right

In Java, do not forget to double the backslashes:

String regex = "(?<![\\d,.])(?:\\d{1,3}(?:(?=([.,]))(?:\\1\\d{3})*)?|\\d+)(?:(?!\\1)[.,]\\d{1,2})?(?![,.\\d])";
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thank you Wiktor Stribiżew, i have to understand that, because it's not immediately understandable for me, and than that could be the solution. – unknown_dcba Jun 18 '20 at 14:20