tags:

views:

115

answers:

3

Lets say I need to match a pattern if it appears 3 or 6 times in a row. The closest I can get is something like \d{3,6} but that doesn't quite do what I need.

'123' should match
'123456' should match
'1234' should not match

+6  A: 
^(\d{3}|\d{6})$

You have to have some sort of terminator otherwise \d{3} will match 1234. That's why I put ^ and $ above. One alternative is to use lookarounds:

(?<!\d)(\d{3}|\d{6})(?!\d)

to make sure it's not preceded by or followed by a digit (in this case). More in Lookahead and Lookbehind Zero-Width Assertions.

cletus
This looks good, thanks. But what if the pattern is much larger than just \d? I guess I could do some string interpolation when building the regular expression but is there a better way to reuse sub-patterns?
In that case you would want to use the {1,2} format, i.e., ((<baseRegex>){3}){1,2}
Alan Moore
+2  A: 

How about:

(\d\d\d){1,2}

although you'll also need guards at either end which depend on your RE engine, something like:

[^\d](\d\d\d){1,2}[^\d]

or:

^(\d\d\d){1,2}$
paxdiablo
+1  A: 

First one matches 3, 6 but also 9, 12, 15, .... Second looks right. Here's one more twist:

\d{3}\d{3}?
Sean Owen
First and second what? If you're referring to someone else's answer, you should say which one it is. These answers don't always appear in the same order.
Alan Moore