LINUX.ORG.RU

Секреты регулярных выражений (regular expressions): Часть 1. Диалекты и возможности. Составление регулярных выражений

 ,


0

0

Словосочетание «регулярные выражения» слышал (или видел) каждый, чья деятельность так или иначе связана с использованием компьютеров. Многие применяют простейшие варианты регулярных выражений чуть ли не ежедневно, даже не подозревая об этом. Обычно им уделяется не слишком много внимания и, как правило, в контексте конкретной утилиты (grep, sed, less) или языка программирования (Perl, Python и т.д). В данном цикле статей я попытаюсь обобщить информацию о регулярных выражениях, сосредоточившись при этом не на элементарных «обучающих» примерах, которые всем известны, а на более тонких аспектах практического использования.

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

>>> Подробности

★★★

Проверено: annoynimous ()

Ответ на: комментарий от bobrik

чего стоит быдлокодопаттерн - определение реасширения файла режекспом!

wfrr ★★☆ ()
Ответ на: комментарий от wfrr

>это ненужно 8) парность скобок не должна определятсья с помощью режекспов

Ну, рекурсия щас заменяется на зацикленный регэксп, по крайней мере при обработке всяких bb-тегов, например. ) Работает отлично ) Тока производительность страдает. А если б это всё было в одной обработке текста, было бы куда лучше, мечта прям ) Я скока в своё время прочёл, наэксперементировал в пхп, но нифига ) Хотя в мануале было написано, что вроде рекурсия в регулярках пхп поддерживается. )

PGArchangel ()

Не самая бесполезная статья на этот раз.

kernelpanic ★★★★★ ()
Ответ на: комментарий от svs

+1
Книга Джефри Фридла - это лучшее, что есть по регулярным выражениям. Читается взахлёб.

avol ()
Ответ на: комментарий от PGArchangel

Индусизм это религия программистов. Ога. bb теги отлично парсятся конечным автоматом.

wfrr ★★☆ ()

С хтмл-детектором похоже что-то не то...Я в свое время в своем быдлокоде использовал примерно такое:

"/<(\/?)(\w+)([^>]*)>/e"
с строкой подстановки
"'[\\1'.strtoupper('\\2').'\\3]'"
А вообще полезная вещь регэкспы, развивает ГМ...

Fat_Green_Liar ()

Статья ниочем, но для новичков пойдет в качестве знакомства. Школьников на ЛОРе много стало, им полезно будет почитать. Уверен, что не все из них слышали про RegExp'ы

irq ()
Ответ на: комментарий от dimon555

Не знаю, особо не изучал, вообще мне не нравится этот путь, не понимаю, зачем отказываться от O(N) скорости разбора, за некоторые спорные преимущества.

Legioner ★★★★★ ()
Ответ на: комментарий от Legioner

> зачем отказываться от O(N) скорости разбора

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

погуглите «awk one liner», «sed one liner» и напишите то же циклами. Получите более чем на порядок (думается - на два) - больше буккаф.

anonymous ()

Прочитал. Секретов не увидел. На таком уровне я учил регекспы 12 лет назад по книжке с верблюдом. Причем там это был всего лишь один из разделов.

С тех пор, правда, я не сильно далеко ушёл.

ebonent ★★ ()
Ответ на: комментарий от Legioner

логи обрабатывать конечными автоматами — тот ещё путь, ага

bobrik ()

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

У меня собралась такая коллекция:


Особенности регулярных выражений grep в командной строке Linux

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

Пример:

# dmesg | grep "\(sata\)\|\(SATA\)"


Регулярные выражения в sed

В потоковом редакторе sed, для того чтобы спецсимволы рассматривались как обычные символы, можно их экранировать обратным слешем. А можно в качестве разделителей полей вместо прямого слеша «/» использовать двоеточие ":".

Пример. Нужно закомментировать в *.cpp файле строку «namespace prog1 {», то есть добавить перед строкой символы «//». Вот несколько вариантов, как это сделать:

sed -i 's/namespace prog1 {/\/\/ namespace prog1 {/' file.cpp
sed -i 's:namespace prog1 {:// namespace prog1 {:' file.cpp
sed -i 's:namespace prog1 {:// &:' file.cpp


Регулярные выражение в MC

При поиске файлов, в MC можно указывать маску файлов таким образом:

(*.cpp)|(*.h)

Примечание: в версии 4.7.0-pre-1 и старше не работает. Разработчики рекомендуют писать маску в виде «*.cpp, *.h», но она тоже не работает.


Регулярные выражения в среде Code::Blocks

В IDE Code::Blocks в разных местах регулярные выражения трактуются по-разному.

1. Проверка регулярных выражений (плагин)

Особенности: символы вида "(" автоматически считаются разметкой регвыра, и чтобы просто указать символ "(", его надо экранировать обратным слешем.

Пример 1: найти в тексте строку drawpic(picidxanm(«main_monkey_finger»)) и выделить параметр функции picidxanm. Для этого нужно использовать выражение:

drawpic\t*\(+\t*picidxanm\t*\(+\t*(.*)\t*\)+\t*\)+

2. Поиск и замена в тексте

Особенности: символы вида "(" считаются обычными символами. Чтобы делать подвыражения, надо скобки экранировать обратным слешем.

Пример 2: чтобы найти строку из примера 1, надо воспользоваться выражением

drawpic\t*(+\t*picidxanm\t*(+\t*\(.*\)\t*)+\t*)+
xintrea ()
Ответ на: комментарий от xintrea

Народ ! Кто в курсе что с вайном то ? На дворе уже следующая пяница :(
Они что релиз 2.0 готовят что ли ?

mx_ ()
Ответ на: комментарий от anonymous

Язык SQL всё таки не компактный, но относительно очевидный чего не скажешь о регулярных выражениях. Достаточно хотя бы посмотреть на эту статью, чтобы понять сколько неожиданностей и скрытных нюансов может содержать в себе незамысловатый паттерн. Выбор между страницами кода с циклами и регулярными выражениями совсем не между компактностью и объёмом, а между качеством, временными затратами и быстротой написания паттерна.

anonymous ()
Ответ на: комментарий от xintrea

В качестве разделителей sed-у можно указывать вообще [почти] любой символ.

$ echo boo | sed 's/b/f/'
foo
$ echo boo | sed 's@b@f@'
foo
$ echo boo | sed 's:b:f:'
foo
$ echo boo | sed 's|b|f|'
foo
$ echo boo | sed 's.b.f.'
foo
$ echo boo | sed 's1b1f1'
foo
anonymous ()

Эта часть не айс. В принципе, посмотрел тред - до меня уже более-менее все сказано.

yaws ()
Ответ на: комментарий от anonymous

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

научитесь их готовить.

Кстати, статья - очень начальная. Тема lookahead, без которых не напишешь сколько-нибудь продвинутых выражений - не раскрыты.

Я использую регэкспы интенсивно для кастом парсеров. В том числе, и генерируя и кеша выражения на-лету. Т.е. на входе - почти человеческий язык, понятных бухгалтерам (хоть в виде таблиц, что включается, что исключается, какие диапазоны эккаунтов итд. Тысячи, десятки тысяч выражений. Которые автоматом преобразуются из типа «7~4*, 7~5*(excluding 735107030, » + «7~550*, 7~551*, 7~555* , 7~558*, 7~560*, 7~565*, 7~5407640, 7~5407650, 7~5407840,7~570*)»
в «7.4.*|7(?!35107030|.550|.551|.555|.558|.560|.565|.5407640|.5407650|.5407840|.570).5.*

или из „F31042 to F31085, F39042 to F39085“ -> „F310(4[2-9]|[567][0-9]|8[0-5]) *|F390(4[2-9]|[567][0-9]|8[0-5]) *“

или „7* (excluding 735107030, 7~550,7~551)“ -> „7(?!35107030|.550|.551).*“)

(это самые простые. Чаще списки - сотни номеров в разных комбинациях)

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

а потом тысячи правил очень эффективно процессятся.

Теперь напишите это в циклах и посмотрим - сколько раз вы идёте от начала каждого из стрингов. Бьюсь об заклад - что закешенные (пре-компилированные) регэкспы сделают это быстрее. Это важно, когда таких проверок - тысячи. Например, при обработке отчётности на уровне страны или области. Миллионы отчётов.

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

Например, есть приложения обрабатывающие номера машин в реальном времени, а паттерны (правила) всё время меняются, как и законы. Что делать - всё время компилировать код?

anonymous ()

«Секреты» - это скрытые вещи, а у регэкспов какие секреты?!! Для тех, кто не читал доки, все регэкспы - один большой секрет! :)
Статью не читал, но наверное для новичков полезная, +1.

matumba ★★★★★ ()

“Some people, when confronted with a problem, think «I know, I'll use regular expressions.» Now they have two problems” ©
Особенно в таких примерах.

x3al ★★★★★ ()
Ответ на: комментарий от anonymous

> Не понимаю, почему в мой любимый фреймворк Qt встроили какую-то кастрированную реализацию.

А чего там не хватает?

ikm ★★ ()
Ответ на: комментарий от anonymous

regexp: реальный искусственный интеллект

Порадовал anonymous (07.05.2010 23:09:44).

Для народного хозяйства лучший искусственный интеллект — это регэкспы, а не C++ и тем более LISP.

olecom ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.