Я искал твердую статью, когда требуется двойное экранирование, а когда нет, но я ничего не смог найти. Возможно, я не выглядел достаточно тяжело, потому что я уверен, что где-то есть объяснения, но давайте просто попробуем найти следующего парня, у которого есть этот вопрос!
Возьмем, к примеру, следующие шаблоны регулярных выражений:
/\n/ /domain\.com/ /myfeet \$ your feet/
Ничего плохого в этом нет? Хорошо, давайте использовать эти примеры в контексте функции preg_match PHP:
$foo = preg_match("/\n/", $bar); $foo = preg_match("/domain\.com/", $bar); $foo = preg_match("/myfeet \$ your feet/", $bar);
Насколько я понимаю, обратная косая черта в контексте цитируемого значения строки вытесняет следующий символ, и выражение передается через значение строки в кавычках.
Будет ли предыдущее быть похожим на последующее, и не вызывает ли это ошибки ?:
$foo = preg_match("/n/", $bar); $foo = preg_match("/domain.com/", $bar); $foo = preg_match("/myfeet $ your feet/", $bar);
Что не то, что я хочу? эти выражения не совпадают с приведенными выше.
Разве мне не пришлось бы писать им двойное спасение?
$foo = preg_match("/\\n/", $bar); $foo = preg_match("/domain\\.com/", $bar); $foo = preg_match("/myfeet \\$ your feet/", $bar);
Так что, когда PHP обрабатывает строку, она пропускает обратную косую черту в обратную косую черту, которая затем остается в том случае, когда она передается интерпретатору PCRE?
Или PHP просто волшебным образом знает, что я хочу передать эту обратную косую черту в интерпретатор PCRE … я имею в виду, как он знает, что я не пытаюсь \"
избежать цитаты, которую я хочу использовать в своем выражении», или просто двойной нужно ли использовать TRIPLE для цитаты? \\\"
Вы знаете, так что цитата сбежала, а двойной остался?
Что такое эмпирическое правило?
Я просто сделал тест с PHP:
$bar = "asdfasdf a\"ONE\"sfda dsf adsf me & mine adsf asdf asfd "; echo preg_match("/me \$ mine/", $bar); echo "<br /><br />"; echo preg_match("/me \\$ mine/", $bar); echo "<br /><br />"; echo preg_match("/a\"ONE\"/", $bar); echo "<br /><br />"; echo preg_match("/a\\\"ONE\\\"/", $bar); echo "<br /><br />";
Вывод:
0 1 1 1
Итак, похоже, почему-то это не имеет значения для котировок, но для знака доллара требуется двойной побег, как я думал.
Строки с двойными кавычками
Когда дело доходит до выхода из двойных кавычек, правило состоит в том, что PHP будет проверять персонаж сразу после обратного слэша.
Если соседний символ находится в наборе ntrvef\$"
или если после него следует числовое значение ( здесь можно найти правила), он оценивается как соответствующий управляющий символ или порядковое (шестнадцатеричное или восьмеричное) представление соответственно.
Важно отметить, что если указана некорректная escape-последовательность, выражение не оценивается, и обратная косая черта и символ остаются. Это отличается от некоторых других языков, где неверная escape-последовательность приведет к ошибке.
Например, "domain\.com"
будет оставлен как есть.
Обратите внимание, что переменные также расширяются внутри двойных кавычек, например, "$var"
необходимо экранировать как "\$var"
.
Одиночные кавычки
Начиная с PHP 5.1.1, любая обратная косая черта внутри одиночных кавычек (и за ними следует хотя бы один символ) будет напечатана как есть, и никакие переменные не будут заменены. Это, безусловно, самая удобная особенность одиночных кавычек.
Обычные выражения
Для ускорения регулярных выражений лучше оставить preg_quote()
для preg_quote()
:
$foo = preg_match('/' . preg_quote('mine & yours', '/') . '/', $bar);
Таким образом, вам не нужно беспокоиться о том, какие символы должны быть экранированы, поэтому он хорошо работает для ввода пользователем.
См. Также: preg_quote
Обновить
Вы добавили этот тест:
"/me \$ mine/"
Это оценивается как "/me $ mine/"
; но в PCRE значение $
имеет особое значение (это привязка конца объекта).
"/me \\$ mine/"
Это оценивается как "/me \$ mine/"
и поэтому обратная косая черта сбрасывается для самого PHP, а $
– для PCRE. Это работает только случайно.
$var = 'something'; "/me \\$var mine/"
Это оценивается как "/me \something"
, поэтому вам нужно снова избежать $
.
"/me \\\$var mine/"
Используйте одинарные кавычки. Они предотвращают появление escape-последовательностей.
Например:
php > print "hi\n"; hi php > print 'hi\n'; hi\nphp >
Всякий раз, когда у вас есть некорректная escape-последовательность, PHP фактически оставляет символы буквально в строке. Из документации :
Как и в одиночных кавычках, экранирование любого другого символа приведет к тому, что обратная косая черта также будет напечатана.
Т.е. "\&"
действительно интерпретируется как "\&"
. Существует не так много escape-последовательностей, поэтому в большинстве случаев вы, вероятно, избегаете одной обратной косой черты. Но для согласованности побег с обратной косой чертой может быть лучшим выбором.
Как всегда: знайте, что вы делаете 🙂
OK Итак, я сделал еще несколько тестов и обнаружил ПРАВИЛО ТОМЫ при инкапсуляции PCRE в DOUBLE QUOTES, выполняется следующее:
$
– Требуется двойной escape, потому что PHP будет интерпретировать это как начало переменной, если текст сразу же следует за ней. Слева безвозвратно, и это покажет конец вашей иглы и сломается.
\r\n\t\v
– Специальные escape-строки PHP, требуется только один escape.
[\^$.|?*+()
– Специальные символы RegEx, требуется только один выход. Двойной побег, похоже, не нарушает выражения при ненужном использовании.
"
Котировки, очевидно, должны быть экранированы из-за инкапсуляции, но нужно только один раз убежать.
\
– Поиск обратной косой черты? Используя инкапсуляцию двойного кавычки вашего выражения, это потребует 3 побегов! \\ (всего четыре обратных косых черты)
Что-нибудь мне не хватает?