Примеры регулярных выражений

15.11.2009

В этой статье я хочу собрать целую коллекцию регулярных выражений. Зачем это нужно? Ну, во-первых, начинающим программистам будет очень полезно поковыряться здесь и разобраться, что к чему, как работают эти самые регулярные выражения. Во-вторых здесь есть очень сложные по структуре регулярные выражения, до которых не всякий ещё и додумается. А ещё эта статья будет полезна для автора и всей нашей команды в целом, так как к регэкспам приходится возвращаться довольно часто, а всего в голове не удержишь.

Мы абстрагируемся от конкретных языков программирования, здесь нет никаких конкретных примеров. Статья целиком и полностью посвящена только регэкспам.

Все приведённые ниже выражения полностью протестированы и готовы к употреблению в языке PHP с функциями preg_replace, preg_match и так далее. Что касается других языков, то, скорее всего, они заработают, но это не 100%. Например, в JavaScript нужно добавить модификатор g, чтобы он искал по всему тексту.

Статья разбита на небольшие подразделы, чтобы было легче ориентироваться.

Новинка! Кликните на регулярное выражение, чтобы увидеть его в действии.

Разбор HTML кода

Найти на странице все теги, ищется непосредственно тег, будь то открытый или закрытый.

/<.*?>/

Найти на странице текст, заключенный в тег <p>...</p>. Очень неплохо парсит страницы, rss и xml.

/<p.*?>(.*?)<\/p>/i

Найти на странице текст, заключенный в тег <p>...</p>, внутри которого отсутствуют слова foo и bar. Иногда требуется найти либо все теги за исключением некоторых с определенным текстом или просто все теги кроме некоторых определенного класса. Несмотря на то, что задача решается неочевидно, её можно решить с помощью регулярных выражений.

/<p>(?:(?!foo|bar).)*?<\/p>/is
/<p(?:(?!class\s*=\s*["'`]?bad["'`]?).)*?>.*?<\/p>/is

Найти на странице текст внутри любого парного тега (<sometag attribute="...">...</sometag>)

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

Найти на странице фразы в кавычках, не включая в поиск теги (теги нужно исключить, так как там тоже бывают кавычки, но их назначение чисто техническое). Немного сложновато, но что поделать.

/(?<!<)(?=[^<>]*)"(?:[^<>]*?|<.+?>)*"(?=[^<>]*)(?!>)/

Найти на странице все ссылки. Этот рег в один карман кладет линк, а в другой — название ссылки. Казалось бы, нехитрая операция, но если следовать спецификациям, выражение принимает несколько угрожающий вид. Но зато найдет любые урлы, даже кривые.

/<a.+?href\s*=\s*["']?((?<=")[^"]*(?=")|(?<=')[^']*(?=')|[^ >]*)(?>[a-z]+\s*=\s*(?:["'].*?["']|^[ >]*)|.)*?>(.*?)<\/a>/si

Проверка данных на корректность.

Является ли строка числом. Существует два типа чисел: целые и рациональные. Здесь ^ означает, что поиск ведётся от начала строки, а $ — что поиск ведётся до конца строки.

Целое:
/^-?[0-9]+$/
Рациональное:
/^-?[0-9]*[.,]?[0-9]*(?:e[+-]?[0-9]+)?$/

Трюки с регулярными выражениями

Выделение строк внутри кавычек с учётом экранирования кавычек. Иногда требуется получить строку целиком внутри кавычек, но нужно учитывать что внутри строки могут тоже быт кавычки (они экранируются обычно символом \). Вот пример такой строки: "abc\"a\"xyz"

/"(?>\\"|.)*?"/

Выделение РНР кода. Пусть нужно из какого-то файла выбрать только РНР код миную HTML. Тут могут встретиться такие подводные камни, как символ ?> внутри кавычек. Вот как это обходить:

/<\?(?>['"](?>\\['"]|.)*?['"]|.)*?\?>/

Рекурсивные регулярные выражения. Предположим, есть множество вложенных скобок, причём скобки могут быть вложены одна в другую. А нужно делать так, чтобы вложенность учитывалась корректно: сколько стоит открывающих скобок, столько должно быть закрывающих. В этом примере ищутся все функции тангенса.

/(?=(tg(\((?:[^()]|(?2))*\))))/

Выделить какой-то тег на странице. Учтем, что тег может быть вложен сам в себя.

/(?=(<div.*?>(?>(?1)|.)*?<\/div>))/s

Выделить вообще все теги на странице. Это выражение найдёт все теги, сохраняя их вложенность.

/(?=(<([a-z]+).*?>(?>(?1)|.)*?<\/\2>))/s

Назад
blog comments powered by Disqus