正则表达式正好用2替换2个反斜杠

I have a string where 2 backslashes must become 3 backslashes. With all the escaping of backslashes, I can't do it and nothing's working.

For example:

  • aaaaa\\aaaaa must become aaaaa\\\aaaaa
  • aaaaa\\\aaaaa STAYS aaaaa\\\aaaaa (2 backslashes in a row must not be detected)

I managed this, which works in regex101.com:

(\\\\)([^\\])

so in php, it would be:

preg_replace('/(\\\\)([^\\])/', '\\\$2', $bob);

But php gives me this error message:

preg_replace(): Compilation failed: missing terminating ] for character class at offset 10

So I don't know if it's a bug of PHP, but I need another way of doing this and I can't find the solution on google.

Try this regex:

(?<!\x5C)\x5C{2}(?!\x5C)

Backslashes can be a real nightmare here. It's better to use the ASCII code of the backslash right into the regex.

Sample code:

define('THREE_SLASHES', preg_quote('\\\\\\'));
define('RE_TWO_SLASHES_ONLY', '~(?<!\x5c)\x5c{2}(?!\x5c)~');

$test='aaaaa\\\\aaaaa';
echo preg_replace(RE_TWO_SLASHES_ONLY, THREE_SLASHES, $test) . '<br>';

$test='aaaaa\\\\\\aaaaa';
echo preg_replace(RE_TWO_SLASHES_ONLY, THREE_SLASHES, $test) . '<br>';

Output

aaaaa\\\aaaaa
aaaaa\\\aaaaa

You might like to take advantage of preg_quote here:

$in1 = <<<'EOD'
aaaaa\\aaaaa
EOD;
$in2 = <<<'EOD'
aaaaa\\\aaaaa
EOD;

echo "input 1: $in1";
echo "input 2: $in2";

$q = preg_quote('\\','/');

echo "output 1: " . preg_replace("/(?<!$q)$q$q(?!$q)/", "$q$q$q", $in1);
echo "output 2: " . preg_replace("/(?<!$q)$q$q(?!$q)/", "$q$q$q", $in2);

I used a nowdoc (available since PHP 5.3.0) to define the input string so that it can be seen exactly as it looks. No parsing is done inside a nowdoc.

$q is now an escaped single backslash that can be used in preg_replace wherever you wanted to use a literal \ before.

The regular expression uses negative lookbehind (?<!$q) and negative lookahead (?!$q) to ensure that the two slashes in the middle aren't preceded or followed by a slash.

Output:

input 1: aaaaa\\aaaaa
input 2: aaaaa\\\aaaaa
output 1: aaaaa\\\aaaaa
output 2: aaaaa\\\aaaaa

preg_quote is normally used for variables longer than one character, so might be seen as overkill here. Instead of using it, you could define $q = '\\\\'; (two string-escaped backslashes) and that would achieve the same outcome.