user1580866
user1580866

Reputation:

Converting regex from ruby to PHP

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

Answers (1)

James Lim
James Lim

Reputation: 13054

The problem lies with your backslashes.

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

Related Questions