Для тестирования и отладки регулярных выражений идеально подходит программа RegexBuddy (http://www.regexbuddy.com). Чтобы отлаживать следующие примеры нужно во вкладку Test скопировать HTML какой-либо страницы или вбить несколько тегов самим.
Задача — найти в HTML все теги IMG и вытащить из тегов значения атрибутов SRC и ALT.
Первая часть задачи найти все HTML теги решается довольно просто таким регулярным выражением:
<img .*?>Не забудьте поставить галочки на "Dot matches newline" и "Case insensitive"

Выражение
.*? не совсем то, что нам нужно. Внутри тега IMG может оказаться много атрибутов, в любой последовательности, значания атрибутов могут быть заключены в одинарные, двойные кавычки или не заключены в кавычки вообще. Попробуем для начала отловить атрибут SRC
\s+src\s*=\s*Выражением отлавливаем предшествующие пробельные символы, а также необязательные пробельные символы до и после знака равно.
В выражении не учтено значение атрибута, которое может быть заключено в одинарные или двойные кавычки.
И тут на помощь нам приходят Backreferences и Named Capturing Group.
\s+src\s*=\s*(?P<qt1>[\"\'])(?P<src>.*?)\k<qt1>
Итак, выражение
(?P<qt1>[\"\']) создаёт именованную группу "qt1" в которую входит символ " или '. Далее идет именованная группа src, куда лениво захватываются все символы до закрывающей кавычки.
Backreference
\k<qt1> гарантирует, что закрывающая кавычка будет соответствовать той, что была использована в начале и захвачена под именем qt1.Заметьте на рисунке как отладчик RegexBuddy выделил более темным цветом символы группы с именем src.
Аналогично можно будет построить регулярку для alt.
Объеденим атрибуты alt, src и все остальные
(.*?). Полученная регулярка выглядит чуть сложной, поэтому сначала пояснения:
выражение
(?:) аналогичнa (), с тем различием, что значение внутри первых скобок (?:) не захватывается в результат.Наша регулярка схематично выглядит так:
<img(?: (?:атрибут src)|(?:атрибут alt)|(?:остальные атрибуты) )*/?>т.е. поле img могут встретится "атрибут src" или "атрибут alt" или остальные, причем всё это объединено в группу, которая может повторяться несколько раз.
Тег IMG заканчивается необязательным знаком / и следом за ним >
Вот что мы получим:
<img(?:(?:\s+src\s*=\s*(?P<qt1>[\"\'])(?P<src>.*?)\k<qt1>)|(?:\s+alt\s*=\s*(?P<qt2>[\"\'])(?P<alt>.*?)\k<qt2>)|(?:.*?))*/?>
Осталась самая малость. Как быть со случаем, если кавычки не указаны?
в этом случае выражение
\s+src\s*=\s*(?P<qt>[\"\'])(?P<src>.*?)\k<qt>распадается на 2 варианта
\s+src\s*=\s*(с кавычками|без кавычек)Итак расширенный вариант, где src значение атрибута src понимается как с кавычками, так и без:
<img(?:(?:\s+src\s*=\s*(?:(?:(?P<qt1>[\"\'])(?P<src>.*?)\k<qt1>)|(?:(?P<src>\S+))))|(?:\s+alt\s*=\s*(?P<qt2>[\"\'])(?P<alt>.*?)\k<qt2>)|(?:.*?))*/?>
Особо въедливым предоставим самим расширить регулярку, чтобы alt также понимался без кавычек. (в таком случае естественно значение не должно содержать пробелы)
UPD: Данная регулярка не претендует на универсальность. Есть вероятность ложных срабатываний внутри закомментированных блоков, кусков javascript, блогов типа PRE, где фактически изображения не выводятся и т.п.
Если парсить страницу целиком, желательно перед этим убрать со страницы скрипты и комменты, блоки PRE (отдельной регуляркой), хотя и это не решит проблем с консткукциями вида
onmouseover=«document.write('<img src=...')»UPD2: Карма после статьи стала меньше, чем до публикации… Мотивация однако!
UPD3: Перенес в самый подходящий для темы блог, надеюсь никто не возражает :)

