Regex для замены string1 на string2, за исключением тегов html, ИЛИ как части URL-адреса (вне html) - PullRequest
1 голос
/ 29 августа 2009

Мне нужно выполнить операции поиска и замены на больших блоках HTML. Я не хочу изменять что-либо, что является частью HTML-тега (например, URL-адреса) - я также не хочу изменять URL-адреса вне HTML-тегов. У меня есть частичное решение для сопоставления слова, которое не находится внутри HTML ( src ):

 word(?!([^<]+)?>)

, хотя regex buddy также говорит, что это будет совпадать:

 (?!([^<]+)?>)word

Итак, единственное, что осталось сделать, это убедиться, что слово не является частью строки, которая выглядит как URL - вот так:

(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|$!:,.;]*[A-Z0-9+&@#/%=~_|$]

Я не уверен, возможно ли это, я намерен сохранить URL-адреса, присутствующие в тексте и являющиеся частью HTML-содержимого, позволяя при этом выполнять операции поиска и замены для всего остального:

Идеальное решение будет соответствовать DOG и заменено на CAT, как показано ниже

<h1>DOG</h1> -> <h1>CAT</h1>
<h1 class='DOG'>DOG</h1> -> <h1 class='DOG'>CAT</h1>

<p class='DOG'>DOG: http://www.DOG.com/DOGfood.html DOGfood is delicious.</p> -> <p class='DOG'>CAT: http://www.DOG.com/DOGfood.html CATfood is delicious.</p>

Бонусные баллы за эффективность, я почти сошел с ума.

1 Ответ

1 голос
/ 29 августа 2009

Что касается сопоставления «СОБАКИ», а не тега: я бы так и сделал, но вместо этого использовал бы это регулярное выражение:

DOG(?![^<>]++>)

[^<>]++ соответствует одному или нескольким объектам, которые не являются угловыми скобками собственнически . Как только это будет сделано, если следующая вещь не '>', она немедленно сообщит о сбое - без возврата. Вы не можете стать более эффективным, чем это.

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

Я рекомендую вместо этого подход, основанный на чередовании. В одном регулярном выражении вы сопоставляете либо полный HTML-тег, либо полный URL-адрес, либо ваше слово:

<[^<>]++>
|
(https?|ftp|file)://[A-Z0-9+&@#/%?=~_|$]++(?:[?!:,.;-]++[A-Z0-9+&@#/%=~_|$]++)*+
|
DOG

Используйте preg_replace_callback, чтобы применить регулярное выражение, и в обратном вызове вы проверите, что оно соответствует. Если это тег или URL, подключите его снова; если это «СОБАКА», замените ее на «CAT».

Это предполагает, что каждая угловая скобка в файле является частью HTML-тега. Если ваши файлы могут содержать комментарии SGML, вам придется добавить для них альтернативу, перед , для тегов HTML. То же самое касается разделов CDATA. И, конечно, значения атрибутов также могут содержать угловые скобки. По моему опыту, это крайне редко, но при необходимости это тоже можно сделать.

...