Ошибка в регулярном выражении PHP - PullRequest
1 голос
/ 18 июля 2010

В этом коде есть ошибка, я не смог ее найти.Какой пропавший символ мне нужен?

preg_replace(/<(?!\/?(?:'.implode('|',$white).'))[^\s>]+(?:\s(?:(["''])(?:\\\1|[^\1])*?\1|[^>])*)?>/','',$html);

Ответы [ 3 ]

4 голосов
/ 18 июля 2010

Похоже, что среди прочего вы пропускаете одиночную кавычку:

preg_replace('/<(?!\/?(?:' . implode('|',$white) . '))[...
             ^
             here!

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

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

$pattern = <<<EOD
/pattern{embeddedExpression}morePattern/
EOD;

... preg_replace($pattern, ...)
0 голосов
/ 18 июля 2010

Ну, эта часть неверна:

(["'])(?:\\\1|[^\1])*?\1

Это должно соответствовать последовательности, заключенной в одинарные или двойные кавычки, возможно, включая кавычки с обратной косой чертой. Но это не сработает, потому что обратные ссылки не работают в классах персонажей. \1 обрабатывается как число 1 в восьмеричной записи, поэтому [^\1] соответствует любому символу, кроме U + 0001 .

Если кажется, что он работает большую часть времени, это из-за неохотного квантификатора (*?). Первая альтернатива в (?:\\\1|[^\1])*? правильно использует экранированную кавычку, но в противном случае она просто неохотно соответствует любому символу, пока не увидит не экранированную кавычку. Это хорошо работает с правильно сформированным текстом, но добавьте дополнительную цитату, и она станет бесполезной.

Правильный способ сопоставления «чего-либо, кроме захваченной группы № 1» - это (?:(?!\1).)*, то есть использовать по одному символу за раз, но только после того, как предварительный просмотр подтвердит, что это не первый символ захваченного текста. Но я думаю, что вам будет лучше иметь дело с каждым видом цитаты отдельно; это регулярное выражение достаточно сложно, как есть.

'~<(?!/?+(?:'.implode('|',$white).')\b)[^\s>]++(?:\s++'.
'(?:[^\'">]++|"(?:[^"\\]++|\\")*+"|\'(?:[^\'\\]++|\\\')*+\')*+)?+>~'

Обратите внимание на добавление \b (границы слова) после чередования белого списка. Без этого, если у вас есть (например) <B> в вашем списке, вы также непреднамеренно добавите в белый список теги <BODY> и <BLOCKQUOTE>.

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

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

0 голосов
/ 18 июля 2010

Сделайте себе одолжение и используйте DOM и XPath вместо регулярных выражений для анализа HTML на во избежание проблем .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...