Reputation: 10239
I'd like a regex that is either X or Y characters long. For example, match a string that is either 8 or 11 characters long. I have currently implemented this like so: ^([0-9]{8}|[0-9]{11})$
.
I could also implement it as: ^[0-9]{8}([0-9]{3})?$
My question is: Can I have this regex without duplicating the [0-9]
part (which is more complex than this simple \d
example)?
Upvotes: 49
Views: 41216
Reputation: 336418
There is one way:
^(?=[0-9]*$)(?:.{8}|.{11})$
or alternatively, if you want to do the length check first,
^(?=(?:.{8}|.{11})$)[0-9]*$
That way, you have the complicated part only once and a generic .
for the length check.
Explanation:
^ # Start of string
(?= # Positive lookahead, assert that the following regex can be matched here:
[0-9]* # any number of digits (and nothing but digits)
$ # until end of string
) # (End of lookahead)
(?: # Non-capturing group, match either
.{8} # 8 characters
| # or
.{11} # 11 characters
) # (End of alternation)
$ # End of string
Upvotes: 77
Reputation: 91508
With Perl, you could do:
my $re = qr/here_is_your_regex_part/;
my $full_regex = qr/$re{8}(?:$re{3})?$/
Upvotes: 2
Reputation: 4910
For those of us looking to capture different lengths of the same multiple try this.
^(?:[0-9]{32})+$
Where 32
is the multiple you want to capture all lengths for (32, 64, 96, ...).
Upvotes: 3