0

I'm trying to use preg_replace to escape all special characters in a multi-line string with a backslash, but this string gets passed out and passed back in repeatedly, so to avoid any confusion I wanted to use a regex which only escapes un-escaped special characters (also excluding spaces, newlines, carriage returns and the escape character itself). I.e.,:

$foo \$bar :\:\n

Should be escaped to become:

\$foo \$bar \:\:\n

And NOT escaped twice like below:

\$foo \\$bar \:\\:\\n

I've gotten close with the following:

preg_replace("/([^\\\\])([^a-z0-9\\\\ \r\n])/i","$1\\\\$2",$input);

But when two of the same special characters appear in sequence, only the first of the two gets escaped.

For example:

....

Becomes:

\..\..

But really I want:

\.\.\.\.

Sorry for the ridiculous issue, or if i'm doing anything stupid! Thanks in advance :)

Harry Lewis
  • 488
  • 5
  • 12
  • I think it is something to do with the regex being able to match two special characters in sequence, capturing them in group one and group 2, so only escaping one of them. But i would have thougt preg_replace would have gone through from begining to end of string, so it would match the first unescaped character, escape it, then the next unescaped character and so on. Would the correct way to proceed be to prevent a match in group one if it is the same match with group two, or vice versa? How do I do that? – Harry Lewis Sep 23 '16 at 10:46

1 Answers1

1

Try to use negative lookbehind in regex. Like this:

preg_replace("/(?<!\\\\)([^a-z0-9\\\\ \r\n])/i","\\\\$1",$input)
Nick
  • 41
  • 4
  • Thanks, I will try it. What exactly does a negative look behind do? – Harry Lewis Sep 24 '16 at 13:04
  • Looks like this topic is already covered [here](http://stackoverflow.com/questions/2973436/regex-lookahead-lookbehind-and-atomic-groups) – Nick Sep 24 '16 at 15:02