preg_replace_callback to run EXCEPT when inside first argument of .replace()

I want to perform a php preg_match_callback against all single or double-quoted strings, for which I’m using the code seen on https://codereview.stackexchange.com/a/217356, which includes handling of backslashed single/double quotes.

const PATTERN = <<<'PATTERN'
~(?|(")(?:[^"\\]|\\(?s).)*"|(')(?:[^'\\]|\\(?s).)*'|(#|//).*|(/\*)(?s).*?\*/|(<!--)(?s).*?-->)~
PATTERN;

$result=preg_replace_callback(PATTERN, function($m) {
            return $m[1]."XXXX".$m[1];
        }, $test);

but this runs into a problem when scanning blocks like that seen in .replace() calls from javascript, e.g.

x=y.replace(/'/g, '"');

… which treats '/g, ' as a string, with the "');......." as the following string.

To work around this I figure it would be good to do the callback except when the quotes are inside the first argument of .replace() as these cause problems with quoting.

i.e. do the standard callbacks, but when .replace is involved I want to change the XXXX part of abc.replace(/\'/, "XXXX"); but I want to ignore the \' quote/part.

How can I do this?

See https://onlinephp.io/c/5df12 ** https://onlinephp.io/c/8a697 for a running example, showing some successes (in green), and some failures (in red).
(** Edit to correct missing slash)

Note, the XXXX is a placeholder for some more work later.

Also note that I have looked at Javascript regex to match a regex but this talks about matching regex’s – and I’m talking about excluding them. If you plug in their regex pattern into my code it does not work – so should not be considered a valid answer

>Solution :

You can use (*SKIP)(*F) to skip something. For skipping the first argument e.g.:

\(\s*/.*?/\w*\h*,(*SKIP)(*F)|(?|(")[^"\\]*(?:\\.[^"\\]*)*"|(')[^'\\]*(?:\\.[^'\\]*)*')

See this demo at regex101 or your update code


Further I used a bit more efficient pattern for matching the quoted parts, explained here.
The pattern on the skipped side is very simple, you might want to further improve that.

Leave a Reply