Reputation:
I have been trying to convert a regular expression from ruby to PHP, however I have had little luck.
This is the ruby regular expression:
QUOTED_LITERAL = /"[^"\\]*(?:\\.[^"\\]*)*"/
UNQUOTED_LITERAL = /[^\s=,][^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
LITERAL = /(#{QUOTED_LITERAL}|#{UNQUOTED_LITERAL})/
PAIR = /#{LITERAL}\s*=>\s*#{LITERAL}/
And this is my go in PHP:
const PAIR = '/("[^"\\]*(?:\\.[^"\\]*)*"|[^\s=,][^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*)\s*=>\s*("[^"\\]*(?:\\.[^"\\]*)*"|[^\s=,][^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*)/';
However when I run
$result = preg_match_all(self::PAIR, $input, $matches);
I get the error:
preg_match_all(): Compilation failed: unmatched parentheses at offset 62
However when run it through, http://www.phpliveregex.com/ with the test data:
"foo" => "bar", "foo" => bar, foo => "bar"
it seems to work fine.
Not sure whats going on.
Upvotes: 5
Views: 672
Reputation: 13054
I managed to get it to compile after removing all backslashes.
Then, I replaced all double slashes with 4 of them, and preg_match_all()
was able to compile the regex too.
const PAIR = '/("[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|[^\s=,][^\s=,\\\\]*(?:\\\\.[^\s=,\\\\]*|=[^,>])*)\s*=>\s*("[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|[^\s=,][^\s=,\\\\]*(?:\\\\.[^\s=,\\\\]*|=[^,>])*)/';
You might have to edit it to get the exact regex you want. You had the compilation error because \\
was fed to the regex engine as \
, which escaped the immediate square brackets. To encode a literal backslash, you need to use \\\\
- once for the string, and once for the regex engine.
string '\\\\' --becomes--> regex \\ --becomes--> literal \
Ruby doesn't have this problem because its regex syntax is separate from its string syntax.
(Related question: preg_match(): Compilation failed: unmatched parentheses.)
Upvotes: 3