Регулярные выражения: как это понимать

Занимаясь IT уже более 10 лет, твердо уяснил: следует не гоняться за модным, а постигать вечное. Лучше тратить время не на поиск «классненьких программок», а на освоение фундаментальных концепций, таких как сетевые протоколы, классические языки программирования вроде C, XML, SQL, ну и, конечно же, regexp — синтаксис регулярных выражений. О последнем и пойдет речь под катом.


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

^((?>[a-zA-Z\d!#$%&'*+\-/=?^_`{|}~]+\x20*|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)(?>\.?[a-zA-Z\d!#$%&'*+\-/=?^_`{|}~]+)+|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d)){4}|[a-zA-Z\d\-]*[a-zA-Z\d]: ((?=[\x01-\x7f])[^\\\[\]]|\\[\x01-\x7f])+)\])(?(angle)>)$


— выражение для проверки корректности электронного адреса. Аж глаза режет от слэшей, решеток, скобок и т.п. Хочется глядя на такое безобразие употреблять не регулярные выражения, а не очень приличные.

И все-таки, регэкспы — они как люди-дикари, т.е. на лицо ужасные, добрые внутри. Кто с ними подружился — получает мощное преимущество в кодописании. Здесь можно было бы сказать: «А посему — 74.125.87.106/ в помощь!». Однако материалов действительно проясняющих запутанную тему регэкспов, в сети не так уж и много. Один из лучших — статья с сайта IBM (на русском). Неплохо изложена тема и в Википедии. В данном же топике я попробую изложить самые основы, которые можно освоить за одно прочтение. Желающие углубиться смогут потом перейти по указанным ссылкам.

Первое, что бросается в глаза в регэкспах — обилие вспомогательных (не буквенно-цифровых) символов. Люди, которые берутся объяснять эту тему, сразу же начинают перечислять и описывать, все эти скобки, палки, решетки и их назначение. А я бы начал как раз с того, чтобы показать, что в простейшем случае можно искать в тексте просто сочетания букв, например:

echo "To be or not to be" | grep -o -e 'be'
be
be

Здесь мы пропускаем фразу «To be or not to be» через процессор регулярных выражений — утилиту grep. Само выражение задано после ключа -e (сочетание 'be'). Ключ -o указывает, что на экран нужно выводить только фрагменты текста, соответствующие шаблону. Без него выводились бы строки, в которых встречается шаблон.

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

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

echo "To be or not to be" | grep -o -e 'b.'с
be
be
echo "To be or not to be" | grep -o -e 'b..'
be 
echo "To be or not to be" | grep -o -e 'b...'
be o


В этих примерах рассматриваются шаблоны 'b.', 'b..', 'b...'. В первом случае нашлось два вхождения шаблона в фразе: «To be or not to be». Во втором — одно. Почему? Потому что второе be идет в конце предложения и третьего знака после него просто нет. На экран программа вывела не просто be, а be и пробел, т.е. букву b и любые два знака после нее. В третьем случае вывелось 'be o' «To be or not to be» (буква b и любые три знака после нее).

Рассмотрим еще два знака, участвующих в любой реализации regexp: ^ и $. Почему выбраны именно они — сказать трудно. Просто нужно запомнить, что означают они начало и конец рассматриваемого текста:

echo "To be or not to be" | grep -o -e '^.........'
To be or 
echo "To be or not to be" | grep -o -e '.........$'
not to be


То есть в первом случае нужно вывести 9 знаков от начала текста, во втором — от конца.

На этом закончу краткий экскурс, чтобы дальнейшими усложнениями не отбить у читателей аппетит. Вот теперь действительно: «Google в помощь»!
  • +10
  • 23 июля 2010, 17:34
  • yababay

Комментарии (5)

RSS свернуть / развернуть
+
0
Ох с первого раза не понял ничего
Со второго прочтения топика что-то стало проясняться
Спасибо тебе автор!
avatar

Gangsta

  • 23 июля 2010, 18:24
+
0
Писал на на VB6.0 под «Windows» собственную поисковую машинку для своей же
базы данных, поэтому вьехал в текст с первого прочтения.
Доступно и нонятно. Класс !
avatar

Markony

  • 23 июля 2010, 19:00
+
0
Да уж, сколько было разных новомодных технологий а регэкспы вечны
avatar

Sergei_T

  • 24 июля 2010, 11:52
+
0
Ребята из Google давно поняли: с 2004 года в мире программирования ничего принципиально нового не появлялось (пруфлинк искать лень). Поэтому чем глубже забираешься в историю — тем полезнее вещи там находишь. Ведь в 80-х и ранее в IT-сфере работали отборнейшие специалисты, получившие хорошее математическое образование и при этом ограниченные в используемых мощностях. Такого разврата, когда любой школьник имеет в своем распоряжении компьютер, сопоставимый по мощности с майнфреймом из 80-х, не было. Вот и проявляли чудеса смекалки и изворотливости, до которых нынешним guёвым создателям «классненьких программочек» еще расти и расти. Нынче ведь как: открыл GUI IDE, нарисовал мышкой кнопок и полей, навесил на каждую по процедуре — вот тебе и приложение. То, что после компиляции оно будет весить несколько мегабайт и 90% присутствующего в нем кода никогда не будет использовано — это фигня, компьютер стерпит. А вот консольная утилита grep, на одно только изучение возможностей которой можно затратить много часов, если не дней, весит менее 200 килобайт. Пользы же от нее — на миллионы долларов.
avatar

yababay

  • 24 июля 2010, 13:22
+
0
Да, согласен, многие утилиты в linux которыми пользуемся ежедневно написаны давно и основаны на фундаментальных принципах
avatar

Sergei_T

  • 24 июля 2010, 13:27

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.