регулярное выражение в поисках обратной косой черты

почему при поиске обратной косой черты в регулярном выражении вам нужно избегать обратной косой черты 4 раза?

Пример:

$pattern = '/\\\\/';
$string = 'to\m';
preg_match( $pattern, $string, $matches );

echo "<pre>";
print_r($matches);
echo "</pre>";

Возвращает:

Array
(
[0] => \
)

0

Решение

Потому что есть два уровня синтаксического анализа, один из которых выполняется PHP, а второй — механизмом регулярных выражений:

  1. Предполагаемая цель: \
  2. Что ж, мне нужно поместить это в строку без экранирования символа после него: "\\"PHP видит \
  3. Теперь мне нужно вставить это в регулярное выражение: "\\\\" PHP видит \\Регулярный двигатель видит \

Функция preg_quote() избавит вас от путаницы, исключив для вас все метасимволы регулярных выражений. например:

$foo = preg_quote("c:\\some\\path\\or_whatever");
preg_match("/$foo/", $bar);

редактировать

Вы, кажется, думаете об этом как о «единицах \\«, что не похоже на точное описание того, что происходит. Для лучшего примера давайте используем другой символ, который также важен как в PHP, так и в регулярных выражениях, $,

  1. Предполагаемая цель: $
  2. Экранирование для строки PHP: "\$", буквальная строка, видимая PHP $
  3. Экранирование для строки PHP, которая будет интерпретирована как литерал $ в регулярном выражении:
    "\\\$"PHP видит буквальную строку \$регулярное выражение видит буквальную строку $

Проиллюстрированы разными стилями фигурных скобок, представляющих разные уровни побега:

0: $     $
1: \$    [\$]
2: \\\\  [{\\}{\$}]

0: \     \
1: \\    [\\]
2: \\\\  [{\\}{\\}]

0: \\server\$c\Windows
1: [\\][\\]server[\\][\$]c[\\]Windows
2: [{\\}{\\}][{\\}{\\}]server[{\\}{\\}][{\\}{\$}]c[{\\}{\\}]Windows

Что также показывает, почему работа с путями Windows — отстой.

3

Другие решения

Это связано с тем, что обратная косая черта имеет особое значение как в строке php, так и в регулярном выражении, поэтому вы должны экранировать ее дважды:

Чтобы соответствовать одному обратному слешу, регулярное выражение должно быть:

/\\/

Если бы это было:

/\/

, обратная косая черта будет экранировать косую черту, что приведет к недопустимому регулярному выражению, совпадающему с одной косой чертой, но пропущенному завершающему.

Затем это чистое регулярное выражение помещается в строку php, и каждый обратный слэш снова экранируется:

'/\\\\/'
1

Поскольку обратная косая черта — это особый символ, вам нужно дважды его избегать. Так что \\ для первого обратного слеша и \\ для второго.

1