Примеры регулярных выражений
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>/
Найти на странице фразы в кавычках, не включая в поиск теги (теги нужно исключить, так как там тоже бывают кавычки, но их назначение чисто техническое). Немного сложновато, но что поделать.
/(?<!<)(?=[^<>]*)"(?:[^<>]*?|<.+?>)*"(?=[^<>]*)(?!>)/
Найти на странице все ссылки. Этот рег в один карман кладет линк, а в другой — название ссылки. Казалось бы, нехитрая операция, но если следовать спецификациям, выражение принимает несколько угрожающий вид. Но зато найдет любые урлы, даже кривые.
Проверка данных на корректность.
Является ли строка числом. Существует два типа чисел: целые и рациональные. Здесь ^ означает, что поиск ведётся от начала строки, а $ — что поиск ведётся до конца строки.
Целое: /^-?[0-9]+$/ Рациональное: /^-?[0-9]*[.,]?[0-9]*(?:e[+-]?[0-9]+)?$/
Трюки с регулярными выражениями
Выделение строк внутри кавычек с учётом экранирования кавычек. Иногда требуется получить строку целиком внутри кавычек, но нужно учитывать что внутри строки могут тоже быт кавычки (они экранируются обычно символом \). Вот пример такой строки: "abc\"a\"xyz"
/"(?>\\"|.)*?"/
Выделение РНР кода. Пусть нужно из какого-то файла выбрать только РНР код миную HTML. Тут могут встретиться такие подводные камни, как символ ?> внутри кавычек. Вот как это обходить:
/<\?(?>['"](?>\\['"]|.)*?['"]|.)*?\?>/
Рекурсивные регулярные выражения. Предположим, есть множество вложенных скобок, причём скобки могут быть вложены одна в другую. А нужно делать так, чтобы вложенность учитывалась корректно: сколько стоит открывающих скобок, столько должно быть закрывающих. В этом примере ищутся все функции тангенса.
/(?=(tg(\((?:[^()]|(?2))*\))))/
Выделить какой-то тег на странице. Учтем, что тег может быть вложен сам в себя.
/(?=(<div.*?>(?>(?1)|.)*?<\/div>))/s
Выделить вообще все теги на странице. Это выражение найдёт все теги, сохраняя их вложенность.
/(?=(<([a-z]+).*?>(?>(?1)|.)*?<\/\2>))/sНазад
