обратная ссылка на регулярное выражение не работает в PHP PCRE

#php #regex #pcre

#php #регулярное выражение #pcre

Вопрос:

Я хочу сопоставить соответствующие теги, такие как <tag>...</tag> . Я попробовал регулярное выражение

 ~<([^>] )>.*?</1>~
  

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

 ~<(tag)>.*?</tag>~
  

работает, но даже

 ~<(tag)>.*?</1>~
  

сбой.

Я предполагаю, что обратная ссылка здесь не работает.

Кто-нибудь может мне помочь, пожалуйста. Спасибо

PS: Я не использую это для синтаксического анализа HTML. Я знаю, что не должен.

Комментарии:

1. конечно, из-за этого произошел бы жесткий сбой: <a href="ciao">text</a> . Ваше регулярное выражение не может получить этот тег. Я избегаю публиковать вопрос о 400, когда кто-то советует не использовать regex для html xD. Теперь вы отредактировали

Ответ №1:

Вы не показали свой PHP-код, но я предполагаю, что ваше регулярное выражение заключено в двойные кавычки. Если это так, то обратная ссылка 1 фактически преобразуется в символ ASCII до того, как она попадет в PCRE. (Все 123 последовательности интерпретируются как восьмеричные экранирования C-строки там.)

Комментарии:

1. Да. Также не вижу ничего плохого в регулярном выражении. Значит, это должна быть какая-то проблема в контексте PHP.

2. Вот и все! Я использовал двойные кавычки, потому что не знал, что это имеет значение. Большое спасибо

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

Ответ №2:

У меня это сработало…

 $str = '<a></a>';

var_dump(preg_match('~<([^>] )>.*?</1>~', $str)); // int(1)
  

CodePad.

Кроме того, рассматривали ли вы анализатор XML? В противном случае ему не понравится фрагмент HTML, подобный этому…

 <a title="Is 4 > 6?"></a>
  

CodePad.

Комментарии:

1. Кстати, ссылки сейчас мертвы.

Ответ №3:

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

 if (preg_match('~<([^>] )>.*?</1>~', $subject, $regs)) {
    $result = $regs[0];
} else {
    $result = "";
}
  

должно сработать.

Ответ №4:

Используйте одинарные кавычки в шаблоне

 preg_match_all('/(sens|respons)e and 1ibility/', "sense and sensibility", $matches);
print_r($matches);