для обычных людей все программисты — черные маги, а программисты умеющие эффективно и правильно решать задачи регулярными выражениями видимо должны быть чернейшими магами =)
Вообще регулярки очень мощная и при этом довольно таки сложная для понимания штука. И шишек в них — грузовой поезд, для каждой задачи свои. И очень правильно сказано — «Используйте только те регэкспы, которые вы написали сами». Хотя есть несколько регекспов, которые можно и позаимствовать, например валидация email адреса, хотя и для этой задачи есть множество различных регулярок.
Стоит наверное еще добавить один немаловажный пункт:
«Не используйте регулярные выражения для решения простых задач, которые можно решить другими, более простыми и быстрыми средствами» или «Пользуйтесь, но без фанатизма»
Насчёт вложенности:
my $rem;
$rem = qr/ (?>[^()]+|\((??{$rem})\))*/;
$str =~ /\($rem\)/;
Мысль я думая понята. Так с помощью динамич регекспов можно решать различные проблемы вложенности :) В перле есть их поддержка, Интерестно как обстоят дела в др языках.
Вы не поняли. Регулярные выражения они на то и регулярные, что описывают регулярные языки (ну, по идее — в Perl/и др. можно распознавать и более «сложные» языки). А регулярные языки не могут выразить вложенность!
Для более сложного есть контекстно-независимые грамматики, которые удобнее для таких задач. Попробуйте написать парсер XML (или же S-выражений, что проще) на регулярках и на CFG и как говорится, почувствуйте разницу.
Не понял философию про регулярные/нерегулярные языки. Если у вам встречается рекурсивные данные, то от рекурсии не уйти, если только не задать максимальную глубину рекурсии. А в некоторых задачах глубина рекурсии данных может быть большой. В этом случае вам все равно придется рекурсивно парсить. Вопрос только чем — рекурсивными регулярками или рекурсивным кодом.
На практике в PHP очень часто использую рекурсивные регулярки (?R). Один из примеров — парсер уравнения (может быть бесконечное кол-во вложенных скобок). Среди известных примеров, библиотека DbSimple (http://dklab.ru/lib/DbSimple/), ф-ция _expandPlaceholdersFlow — осуществляет подстановку плейсхолдеров. По-моему правильно и удобно.
> Вопрос только чем — рекурсивными регулярками или рекурсивным кодом.
Парсером LL, LR или там GLR (в общем — даешь ему BNF, а он делает свое черное дело). Самое главное — *парсером*. На входе строка (или последовательность token'ов), на выходе — AST.
> На практике в PHP очень часто использую рекурсивные регулярки (?R).
И абсолютно зря. Нормальные люди описывают грамматики в BNF, а затем используют либо Yacc+Flex, либо комбинаторные парсеры.
Не уверен, что Yacc+Flex выйграет у регулярок PHP по сумме коэффициентов
время, потраченное на основение + время потраченное настройку + кроссплатформенность ;)
Еще как выиграет. Все дело в том, что именно *фундментальные ограничения* регулярных выражений и *практическая необходимость* в разборе более широкого класса грамматик, кроме всего прочего, мотивировали создание BNF и таких инструментов, как Yacc/Flex.
в komodo IDE есть отличная тулза — rx toolkit — пишешь текст, пишешь постепенно регексп и оно сразу подвесчивает что нашло. конечно такое можно и самому сообразить…
советую по регулярным выражениям почитать «регулярные выражения. 2-е изд. / Дж. Фридл. — СПб.: Питер, 2003. — 464с (ISBN 5-272-00331-4)»
Хм, не думаю, что издательство «Питер» эту книгу «освободило». Но ввиду мизерного тиража (3000 экземпляров) ничего другого не остается, кроме как скачивать из альтернативных источников :(
во первых с какого перепуга «Используйте только те регэкспы, которые вы написали сами», под конкретную задачу (а она могла решаться не только вами) могут быть написаны вполне не плохие регулярки, а вот то, чего напишите вы, ввиду того, что вы не учитываете всех ньюансов разбора, может работать занчительно мделеней
символ «-» не всегда указывает на диапазон (на пример если он будет в самом начале)
если говорить, что давайте писать не так «…» а вот так «…» то хорошо бы говорить почему именно, довод, «выглядит проще», «красивее» — это не правильно
Я пишу из своей практики. Если кому-то повезло с чужими выражениями, я рад за него. Но в реальности приходиться менять условия и тут придется разобрать чужой регэксп, по-любому.
Скорость работы… пишите проще, меньше шаблонов и больше конкретики — я писал об этом в статье и будут Ваши выражения быстры и верны.
Да, симовол "-" и в конце и в начале диапазона воспринимается как просто символ. Можно это использовать, главное не нарваться на описанную выше проблему. Я регулярно наблюдаю эту ошибку, поэтому решил что это важно.
Мне казалось я написал причины… но все же аргумент за простоту и красоту:
Код, имеет свойство переписываться и для меня важно быстро и безошибочно определить что он делает, поменять его, оставив простоту и ясность. Я всегда могу усложнить код, но упростить, как правило, очень сложно.
Думаю, что про это надо написать. Плюс стоит описать принцип работы, т.е. каким образом обрабатывается строка по регулярному выражению. Сейчас пример не вспомню, но в какой-то книге было это объяснение и в конце приведён регексп типа b*b*b*b*b*b*b*b*b*b*b*$ применительно к строке bbbbbbbbbb, ну и пояснения, что такая регулярка будет выполняться очень долго, так как будет сперва хватать всю строку, потом посимвольно откатываться назад и так для каждого символа (не квантификатора) в регулярке.
С вложенность (как раз парсинг html) строили динамеческие регэкспы, исходя из максимальной длины вложенности. Для большей части html который нам попадался (популярные интернет порталы) хватало вложенности 2-3, иногда в частных случаях 4-5 ( например тэги div вконтакте :) ).
На такой вложенности скорость работы вполне терпима, а вот альтернатива в виде посимвольный разбора строки с составлением объекта-прокси (использовали open source библиотеку на AS3), на больших страницах потребляла на порядок больше системных ресурсов.
немного оффтоп, по поводу IP — недавно обнаружил (что в общем не секрет, просто я как-то пропустил этот момент) что IP резолвятся как в обычном и десятичном представлении, так и в хексе и восьмеричном. То есть взяв скажем ya.ru и один из адресов 77.88.21.8, можем достучаться по нему как 1297618184, 0x4D581508 и 011526012410. Опять же, ничего нового для тех кто знает/помнит особенности IPv4, просто от парсинга IP-адреса вспомнилось.
> В таких случаях лучше делать простой фильтр на откровенно невалидный ввод ( типа SQL injection )
Вы по книгам Фленова учились?
НА SQL-inj НЕ НУЖНО проверять. Нужно просто правильно работать с данными.
Ну и дополнение: не стоит делать BB-теги на регекспах, за исключением тех случаев, когда вам не страшны XSS.
Чтобы сделать BB-коды безопасными, надо использовать алгоритм State Machine. И есть готовые реализации.
Некоторые ошибки при написании регэкспов