3

I have a URI that contains both & and && and I need to split it into an array only at the single & delimiter, e.g. query1=X&query2=A&&B&query3=Y

should print out

array(
0   =>  query1=X
1   =>  query2=A&&B
2   =>  query3=Y
)

I know I can use preg_split but can't figure out the regex. Could someone help?

Tyssen
  • 1,569
  • 16
  • 35

2 Answers2

5

with preg_match_all (all that isn't an isolated ampersand):

preg_match_all('~[^&]+(?:&&[^&]*)*|(?:&&[^&]*)+~', $uri, $result);

with preg_split (check forward and backward with lookarounds):

$result = preg_split('~(?<!&)(?:&&)*+\K&(?!&)~', $uri);

or (force the pattern to fail when there's "&&"):

$result = preg_split('~&(?:&(*SKIP)(*F))?~', $uri);

without regex (translate "&&" to another character and explode):

$result = explode('&', strtr($uri, ['%'=>'%%', '&&'=>'%']));
$result = array_map(function($i) { return strtr($i, ['%%'=>'%', '%'=>'&&']); }, $result);
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
1

Another preg split:

preg_split("/(?<!&)&(?!&)/",$uri)

(Grab an ampersand not followed by or preceded by an ampersand)

chiliNUT
  • 18,989
  • 14
  • 66
  • 106
  • Of the many options that work, this is the most legible and performant on most systems. That said, I do wonder if `parse_str()` isn't the better option for the ultimate end-goal. IOW: I'd love to back up and see the big picture goal instead of the specific question. – Derek Jones Oct 11 '16 at 04:53
  • `parse_str` will biff on this particular case because it does split on each ampersand, so `query2=A`, then you get Empty key=Empty value (because there is exactly nothing between the 2 consecutive ampersands). – chiliNUT Oct 11 '16 at 05:47
  • Also, I agree (at least imho) that my solution is the most legible, but what makes it more performant than the other suggestions? – chiliNUT Oct 11 '16 at 05:48
  • Well it depends on the target string, of course, but some quick benchmarks show that it's magnitudes faster than the non-regex solution, nearly 2x as fast as `preg_match_all()`, and fractions faster than the two `preg_split()` solutions offered by Casimir. Essentially the `preg_split()` methods are a wash performance-wise, in which case I much prefer a direct, non-clever approach. – Derek Jones Oct 12 '16 at 15:52