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

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

ТЕСТ 01: (3 обратной косой черты)

$pattern = "/^[\\\]{1,}$/";
$string = '\\';

// ----- RETURNS A MATCH -----

ТЕСТ 02: (4 обратной косой черты)

$pattern = "/^[\\\\]{1,}$/";
$string = '\\';

// ----- ALSO RETURNS A MATCH -----

Согласно приведенным ниже статьям, 4 предположительно правильный путь, но меня смущает то, что оба теста вернули совпадение. Если оба верны, то 4 предпочтительнее?

РЕСУРСЫ:


person Mahmoud Tahan    schedule 15.06.2012    source источник


Ответы (5)


Дело в том, что вы используете класс символов [], поэтому не имеет значения, сколько буквальных обратных слэшей встроено в него, он будет рассматриваться как один обратный слеш.

например следующие два регулярных выражения:

/[a]/
/[aa]/

для всех намерений и целей идентичны в отношении механизма регулярных выражений. Классы символов берут список символов и «сворачивают» их, чтобы они соответствовали одному символу, в соответствии со строками «для текущего рассматриваемого символа, это какой-либо из символов, перечисленных внутри []?». Если вы укажете две обратные косые черты в классе, то это будет «символ — черная косая черта или это обратная косая черта?».

person Marc B    schedule 15.06.2012
comment
Итак, в обоих случаях механизм регулярных выражений считает это одной обратной косой чертой? - person Mahmoud Tahan; 15.06.2012
comment
\[\] будет экранированием закрывающей скобки. [\\] будет обратной косой чертой в классе символов. один класс char довольно бессмыслен, он ничем не отличается от простого `\\`. - person Marc B; 15.06.2012

// PHP 5.4.1

// Either three or four \ can be used to match a '\'.
echo preg_match( '/\\\/', '\\' );        // 1
echo preg_match( '/\\\\/', '\\' );       // 1

// Match two backslashes `\\`.
echo preg_match( '/\\\\\\/', '\\\\' );   // Warning: No ending delimiter '/' found
echo preg_match( '/\\\\\\\/', '\\\\' );  // 1
echo preg_match( '/\\\\\\\\/', '\\\\' ); // 1

// Match one backslash using a character class.
echo preg_match( '/[\\]/', '\\' );       // 0
echo preg_match( '/[\\\]/', '\\' );      // 1  
echo preg_match( '/[\\\\]/', '\\' );     // 1

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

echo preg_match( '/\\\\s/', '\\ ' );    // 0  
echo preg_match( '/\\\\s/', '\\s' );    // 1  

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

echo preg_match( '/\\\\\s/', '\\ ' );   // 1
echo preg_match( '/\\\\\s/', '\\s' );   // 0

То же самое относится, если внутри класса символов.

echo preg_match( '/[\\\\s]/', ' ' );   // 0 
echo preg_match( '/[\\\\\s]/', ' ' );  // 1 

На приведенные выше результаты не влияет заключение строк в двойные кавычки вместо одинарных.

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

Рекомендация.
Всегда используйте четыре символа обратной косой черты '\\\\' в шаблоне регулярного выражения при поиске совпадения с обратной косой чертой.

Escape-последовательности.

person MikeM    schedule 12.03.2013
comment
Когда я пытаюсь [\], я всегда получаю сообщение: preg_match(): компиляция не удалась: отсутствует завершение] для класса символов по смещению 3 - person CMCDragonkai; 29.11.2013

Чтобы избежать такого непонятного кода, вы можете использовать \x5c Вот так :)

echo preg_replace( '/\x5c\w+\.php$/i', '<b>${0}</b>', __FILE__ );
person Олег Всильдерев&    schedule 30.07.2014
comment
Я просто хочу сказать огромное спасибо за это. Экранирование escape-символов, таких как \n, уже является проблемой, но делать это в регулярном выражении с просмотром назад - проблема. - person Alex Skrypnyk; 04.06.2017
comment
Избегайте back slash только для замены еще тремя символами и обратной косой чертой. Фу! - person Cholthi Paul Ttiopic; 02.04.2018

Я изучал это много лет назад. Это потому, что 1-я обратная косая черта экранирует 2-ю, и они вместе образуют символ «настоящей обратной косой черты» в шаблоне, и этот истинный экранирует 3-й. Таким образом, это волшебным образом заставляет работать 3 обратной косой черты.

Однако обычно рекомендуется использовать 4 обратных слэша вместо неоднозначных 3 обратных слэшей.

Если я в чем-то ошибаюсь, пожалуйста, поправьте меня.

person Scott Chu    schedule 20.01.2014
comment
-1: and this true one escapes the 3rd one Нет. Выполняется только один проход. Третий обратный слэш экранирует ] (что само по себе приводит к ]). - person Lightness Races in Orbit; 20.01.2014
comment
@ Lightness: Тогда почему '/(\\\r)\1+/' будет соответствовать повторяющимся '\' и 'r' (я имею в виду 2 истинных символа)? Вы можете объяснить? - person Scott Chu; 27.01.2014
comment
\r — управляющая последовательность; \] нет. - person Lightness Races in Orbit; 27.01.2014

Вы также можете использовать следующие

$regexp = <<<EOR
schemaLocation\s*=\s*["'](.*?)["']
EOR;
preg_match_all("/".$regexp."/", $xml, $matches);
print_r($matches);

ключевые слова: dochere, nowdoc

person test30    schedule 16.05.2017