Reputation: 2934
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
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 stringSee 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
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
Reputation: 107287
You can use following regex if you want to let trailing comma:
^((\d,?){8})$
Otherwise use following one:
^((\d,?){8})(?<!,)$
(?<!,)
is a negative-lookbehind.
Upvotes: 2