2013-12-11 2 views
3

Я играю с регулярными выражениями, и я попробовал escape-последовательность \ Q .. \ E.Как preg_match обрабатывает разделитель при использовании Q .. E?

Первая попытка:

$regex = '/\Q http:// \E/'; 
var_dump(preg_match($regex, ' http:// ')); 

Он говорит мне, что '\' неизвестен модификатор, вполне понятно.

Вторая попытка:

$regex = '/\Q http:\/\/ \E/'; 
var_dump(preg_match($regex, ' http:// ')); 
var_dump(preg_match($regex, ' http:\/\/ ')); 

Он работает, не соответствует первой строке, но соответствует второй.

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

Я через это сначала отделяет регулярное выражение от модификаторов разделителем (при необходимости обрабатывая экранирование), и после этого механизм регулярных выражений интерпретирует \ Q .. \ E, но это похоже на то, Q, то он не обрабатывает экранированный разделитель таким же образом.

Что происходит именно в этом случае?

Спасибо!

ответ

0

Ограничитель регулярных выражений (/ в этом случае), по-видимому, обрабатывается странно в строке (\ Q ... \ E). Это разделитель, поэтому вам нужно избегать его, поэтому preg может анализировать регулярное выражение из параметров. Но, похоже, это не мешает \ Q и \ E выполнять свою работу по интерпретации обратной косой черты как литералу, а не побегу.

Если вы используете другой разделитель, все работает, как ожидалось:

var_dump(preg_match('@\Q http:// \[email protected]', ' http:// ')); 
2

\Q и \E можно использовать, чтобы игнорировать регулярные выражения метасимволы в шаблоне.

Если, например, строка содержит разделитель /, компиляция с регулярным выражением терпит неудачу или совпадение не выполняется, поскольку оно пытается совместить escape-символ, используемый для выхода из разделителя. Разделители, которые находятся между \Q \E, должны рассматриваться как буквальные символы, а не разделители.

preg_match('~\Q http:// \E~', ' http:// ', $match); 
var_dump($match); 

# => array(1) { [0]=> string(7) " http:// " } 

Использование preg_quote() вместо \Q \E если разделитель может появиться в \Q \E

$text = ' http:// '; 

preg_match('/' . preg_quote($text, '/') . '/', $text, $match); 
var_dump($match); 

# => array(1) { [0]=> string(9) " http:// " } 
1

Почему синтаксис \Q...\E не поддерживает разделитель?

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

+1

Ну, тогда это плохая реализация в PHP, верно? Когда я даю \ E, он не должен искать разделитель. В perl, например, print ("http: //" = ~/\ Q http: \/\/\ E /); дает, что это совпадения. Благодаря! – face

+0

@face: «Плохо», я не знаю, Это выбор. Какая реализация видит экранированные символы как буквенные символы внутри '\ Q ... \ E'? Это всего лишь точка зрения. –

0

Поскольку определение:

Character: \Q...\E 

Description: Matches the characters between \Q and \E literally, suppressing the meaning of special characters 

Специальные символы как указано here и here являются:

. \ + * ? [^] $ () { } = ! < > | : -

Каждый не алфавитно-цифровой, не обратной косой черты, непробельный символ, который используется поскольку разделитель не считается классом специальных символов, а просто разделителями, поэтому мы обнаружим, что:

var_dump(preg_match("+\Q+\E+", "+"));

выбросит подобную ошибку:

Warning: preg_match(): Unknown modifier '\'

Смежные вопросы