Javed Ahamed
Javed Ahamed

Reputation: 2934

RegEx for matching X digits with one optional comma in between digits?

I'm trying to write a RegExp to match only 8 digits, with one optional comma maybe hidden in-between the digits.

All of these should match:

12345678
12,45678
123456,8

Right now I have:

^[0-9,]{8}

but of course that erroneously matches 012,,,67

Example: https://regex101.com/r/dX9aS9/1

I know optionals exist but don't understand how to keep the 8 digit length applying to the comma while also keeping the comma limited to 1.

Any tips would be appreciated, thanks!

Upvotes: 8

Views: 7855

Answers (3)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626853

To match 8 char string that can only contain digits and an optional comma in-between, you may use

^(?=.{8}$)\d+,?\d+$

See the regex demo

The lookahead will require the string to contain 8 chars. ,? will make matching a comma optional, and the + after \d will require at least 1 digit before and after an optional comma.

If you need to match a string that has 8 digits and an optional comma, you can use

^(?:(?=.{9}$)\d+,\d+|\d{8})$

See the regex demo

Actually, the string will have 9 characters in the string (if it has a comma), or just 8 - if there are only digits.

Explanation:

  • ^ - start of string
  • (?:(?=.{9}$)\d+,\d+|\d{8}) - 2 alternatives:
    • (?=.{9}$)\d+,\d+ - 1+ digits followed with 1 comma followed with 1+ digits, and the whole string matched should be 9 char long (8 digits and 1 comma)
    • | - or
    • \d{8} - 8 digits
  • $ - end of string

See the Java code demo (note that with String#matches(), the ^ and $ anchors at the start and end of the pattern are redundant and can be omitted since the pattern is anchored by default when used with this method):

List<String> strs = Arrays.asList("0123,,678", "0123456", // bad
        "01234,567", "01234567" // good
    );
for (String str : strs)
    System.out.println(str.matches("(?:(?=.{9}$)\\d+,\\d+|\\d{8})"));

NOTE FOR LEADING/TRAILING COMMAS:

You just need to replace + (match 1 or more occurrences) quantifiers to * (match 0 or more occurrences) in the first alternative branch to allow leading/trailing commas:

^(?:(?=.{9}$)\d*,\d*|\d{8})$

See this regex demo

Upvotes: 6

Redu
Redu

Reputation: 26161

/^(?!\d{0,6},\d{0,6},\d{0,6})(?=\d[\d,]{6}\d).{8}$/

I guess this cooperation of positive and negative look-ahead does just what's asked. If you remove the start and end delimiters and set the g flag then it will try to match the pattern along decimal strings longer than 8 characters as well.

Please try http://regexr.com/3d63m

Explanation: The negative look ahead (?!\d{0,6},\d{0,6},\d{0,6}) tries not to find any commas side by side if they have 6 or less decimal characters in between while the positive look ahead (?=\d[\d,]{6}\d) tries to find 6 decimal or comma characters in between two decimal characters. And the last .{8} selects 8 characters.

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107287

You can use following regex if you want to let trailing comma:

^((\d,?){8})$

Demo

Otherwise use following one:

^((\d,?){8})(?<!,)$

Demo

(?<!,) is a negative-lookbehind.

Upvotes: 2

Related Questions