Прежде всего, вы не должны анализировать HTML с регулярными выражениями .
Решение 1
Теперь, если вы выполняете исключительно синтаксический анализ img
теги, вы могли бы найти достаточно удовлетворительное решение, как это:
(\b\.jpg|\b\.png)\?(.*?)\"
То есть:
(\b\.jpg|\b\.png) # 1st Capturing Group
\b\.jpg # 1st Alternative: match ``.jpg`` literally
\b\.png # 2nd Alternative: match ``.png`` literally
\? # Match the character ? literally
(.+?) # 2nd Capturing Group
.+? # Match any character between one and unlimited times,
# as few times as possible, expanding as needed.
\" # Match the character " literally
Проблема
В чем проблема?Мы не проверяем, находимся ли мы внутри тега img
.Это будет соответствовать везде в HTML.
Решение 2
Давайте добавим проверку для img > src
:
<img.+?src=\".*?(\b\.jpg|\b\.png)\?(.+?)\"
То есть:
<img # Match ``<img`` literally
.+? # Match any character between one and unlimited times,
# as few times as possible, expanding as needed.
# Needed in case there are rel or alt options inside the img tag.
src=\" # Match ``src="`` literally
... # The rest is same as before.
Проблема
Это действительно делает свою работу?Очевидно, да, но на самом деле нет.
Рассмотрим следующий HTML-код
<img src="data:image/png;base64,iVBORw0KG" />
<div style="background-image: url(../images/test-background.jpg?)">
blah blah
</div>
Это не должно совпадать, верно?Но это так (если вы удалите разрывы строк).Приведенное выше регулярное выражение начинает совпадение с <img src="
и останавливается на ">
тега div
.Группа захвата будет содержать символы от ?
до "
: )
, ее замена нарушит HTML.
Это был только пример, но многие другие ситуации будут совпадать, даже если они не должны.
Другие решения ...?
Независимо от того, сколько ограничений вы можете добавить в свой RegEx и насколько он сложен ... HTML является контекстно-свободнымЯзык , и он не может быть захвачен регулярным выражением, которое распознает только Обычные языки .
В PHP
Все еще уверен, что выбудете использовать регулярные выражения?Хорошо, тогда ваша PHP
функция preg_replace
.Вам нужно только помнить, что он заменит все, что соответствует , а не только группы захвата.Следовательно, вам нужно обернуть то, что вы хотите «запомнить» , в другую группу захвата:
$str = '<img src="folder/img1.jpg?foo">';
$pattern = '/(<img.+?src=\".*?(\b\.jpg|\b\.png)\?)(.+?)(\")/';
$replacement = '$1' . 'bar' . '$4';
$str_replaced = preg_replace($pattern, $replacement, $str);
// Now you have $str_replaced = '<img src="folder/img1.jpg?bar">';