
Памятка по регулярным выражениям
9 февраля 2011
Решил написать шпаргалку по регулярным выражениям. Вдруг я когда-нибудь их подзабуду. Кроме того, этот пост можно считать продолжением к моей серии уроков по Perl.
1. Введение
Пара слов для тех, кто не совсем в курсе, о чем идет речь. Вы видели когда-нибудь маски имен файлов — всякие там *.html, filename.{txt|csv} и тд? Так вот, регулярные выражения — это те же «маски», только более сложные. В умелых руках регулярные выражения могут быть невероятно мощным инструментом. Так или иначе они используются в 95% моих скриптов.
Многие небезосновательно считают, что регулярные выражения — это скорее самостоятельный язык программирования, чем часть какого-либо языка. Регулярные выражения есть в Perl, PHP, Python, JavaScript, конфигурационных файлах Apache… В зависимости от языка, могут иметь место небольшие различия в синтаксисе регулярных выражений, но основные идеи везде одни и те же.
Поэтому, несмотря на то, что все примеры в заметке написаны на Perl, приведенная информация также пригодится программистам, использующим в своей работе любой другой язык. Например, такой код на PHP:
if(preg_match("/[0123456789]/", $text)) {
// в тексте есть цифры
} else {
// в тексте нет ни одной цифры
}
и такой — на Perl:
if($text =~ /[0123456789]/) {
# в тексте есть цифры
} else {
# в тексте нет ни одной цифры
}
делают одно и то же. Как не сложно догадаться по комментариям в коде, здесь идет проверка, содержит ли строка $text хотя бы одну цифру.
2. Простые примеры
Как всегда, учиться будем на примерах. Квадратные скобки в регулярных выражениях означают «здесь должен быть один из перечисленных символов». Например, приведенному выше выражению [0123456789] соответствует любая строка, содержащая хотя бы одну цифру. Аналогично, выражению [abc]соответствует любая строка, содержащая хотя бы одну из первых трех букв латинского алфавита. Чтобы обозначить любой символ, кроме заданных, используется запись [^abcdef], то есть с символом крышки сразу за открывающейся квадратной скобкой.
Пусть нам нужно проверить, содержит ли строка любой символ латинского алфавита. Перечислять все 26 букв не совсем удобно, правда? Специально для таких случаев в регулярных выражениях можно использовать тире в квадратных скобках для обозначения упорядоченного множества символов. Выражению [a-z] будет соответствовать любая строка, содержащая хотя бы одну прописную букву латинского алфавита. По аналогии, приведенный ранее пример с цифрами можно записать более коротко:
if($text =~ /[0-9]/) {
# в тексте есть цифры
} else {
# в тексте нет ни одной цифры
}
И еще пара примеров:
if($text =~ /[a-z0-9]/) {
# в тексте есть цифры и/или прописные буквы
# подходит: abc, ZZaZZ, ===17
# не подходит: EPIC FAIL, @&#^*!@#
}
if($text =~ /[^0-9]/) {
# в тексте есть символы, отличные от цифр
# подходит: abc, 123abc456, 0x1111111111
# не подходит: 123, 123456, 9999999999
}
if($text =~ /[a-zA-Z]/) {
# в тексте есть буквы латинского алфавита
# подходит: ___Abba___, zyx
# не подходит: 0123, ^_^
}
if($text =~ /[a-fA-F0-9]/) {
# текст содержит цифры и буквы от A до F
# подходит: ***777***, DeadC0de, intel, 0_o
# не подходит: Xor, wiki
}
Усложним задачу. Теперь нам нужно проверить не просто наличие или отсутствие определенных символов, а соответствие строки определенному формату. Вот несколько простых примеров:
if($text =~ /num=[0-9]/) {
# подходит: num=1, some_num=000, bebenum=2(&^*
# не подходит: NUM=1, my_num=-1, num=abc
}
if($text =~ /<img src="[^"]+">/) {
# подходит:
# zzz<img src="logo.png">zzz
# <img src="http://example.ru/logo.png">
# не подходит:
# <img src='logo.png'>
# <img src="logo.png" />
}
Внимательный читатель поинтересуется, что это за знак плюса стоит в последнем регулярном выражении? Этот символ означает «один или более символов, указанных перед этим плюсом». Почти то же самое обозначает символзвездочка — «от нуля до сколько угодно символов, указанных перед звездочкой». Например, выражению A+ будет соответствовать последовательность из одного и более символов A, а выражению [0-9]* — любое количество цифр, в том числе и ни одной.
Иногда количество символов нужно задать точнее. Это можно сделать с помощью фигурных скобок. Например, выражению [0-9]{8} соответствует любая последовательность из ровно восьми цифр, а выражению [a-z]{3,8} — последовательность, содержащая от 3-х до 8-и символов латинского алфавита.
Число на второй позиции можно не указывать. То есть выражение [a-z]{3,} также может иметь место. Оно означает «не менее трех прописных букв латинского алфавита». Выражение {0,} полностью аналогично звездочке, а {1,} — плюсу. Выражение {0,1} можно записать более коротко, используя знак вопроса.
Пример (не самый простой, зато интересный):
if($text =~ /<img src=["']{1}https?[^"']+["']{1} *>/) {
# подходит:
# dfgd<img src="http://example.ru/logo.png">dfgdfg
# <img src='https://null' >
# не подходит:
# <img src="logo.png">
# <img src="http://bebebe'bebebe">
}
Если от этого примера у вас закипают мозги, самое время немного попрактиковаться в регулярных выражениях путем написания тестовых программок. Иначе от дальнейшего прочтения у вас будет каша в голове. Если пока что все понятно, идем дальше.