Sometimes I need to make sure some input is comma-separated (or whatever-separated) list of well-structured piece of data. In the real world I needed, for example, to validate this kind of format:
foo{bar:baz,abc:def},xyz,lol{rotfl:true}
, which is comma-separated list of strings with or without arguments list (which are comma-separated too). This example is more complicated, I just mention that to prevent you guys from giving banal answers like:
Why can't you just use explode()?
Which I always get whenever I want to know something about regex better.
For the sake of simplicity, I will use another example. But please remember: this is not actual problem! It's a simplified example of more complex use cases, where I indeed must use regex.
Let's say I need a regex pattern to make sure my string is a list of comma-separated zip codes. Each zip code has format
xx-xxx
, where
x
is any number from 0 to 9 and there is at least one zip code. The list needs to be properly comma-separated, which means:
- No leading comma
- No trailing comma
- No more than one consecutive commas
Normally, I'd do something like this:
$pattern = '#^\d{2}-\d{3}(?:,\d{2}-\d{3})*$#';
That will work. Is there any way to prevent repeating the
\d{2}-\d{3}
part of the pattern? Of course, I can save it to the variable like this:
$zipCodePattern = '\d{2}-\d{3}';
$pattern = "#^$zipCodePattern(?:,$zipCodePattern)*$#";
Although, I'm more than curious if that can be done in the pattern itself.