Комментарии 71
Это конечно 1001 статья про регулярки. Ну ок, лайк, написано неплохо. Про себя замечу, что когда-то я боялась регулярных выражений, но в какой-то момент сделала усилие над собой, и после этого прям затащилась от них, и теперь "вижу" их применение везде (где может и не надо). Вплоть до того, что решаю алгоритмические задачи через регулярные выражения. Например преобразую массив в строку, проворачиваю нужные операции на базе регулярных выражений и возвращаю обратно массив. (Если конечно производительность не критична).
Спасибо за отзыв. Я тоже не любил регулярки, но когда в них разобрался, решил простым языком объяснить их и помочь людям в них разобраться.
и теперь "вижу" их применение везде (где может и не надо)
Это важное уточнение. После того как перестал бояться и полюбил регулярки, очень важно их немедленно разлюбить до приемлемого уровня и использовать только там где они оптимальны
Some people, when confronted with a problem, think «I know, I'll use regular expressions.» Now they have two problems.--Jamie Zawinski
С учётом lookahead и lookbehind они вроде бы тьюринг-полные. Так что в теории с помощью них можно решить любую задачу, но не следует. Попробуйте теперь кс-грамматики и генераторы парсеров - с помощью них можно тоже не только языки парсить.
Например преобразую массив в строку, проворачиваю нужные операции на базе регулярных выражений и возвращаю обратно массив.
И ваш код проходит ревью? Как вы, собственно, объясняете коллегам своё алгоритмическое решение?
Синтаксис (правила написания регулярок) не привязан к какому-то отдельному языку программирования. Поэтому, изучив регулярные выражения, вы сможете пользоваться ими где захотите.Это не совсем так, существуют разные диалекты регулярных выражений. В том же sed, например, чтобы + воспринимался как квантификатор, его необходимо предварять символом \. И этим различия не заканчиваются, я привел это только как пример.
И сведены воедино в книге Фридла Mastering Regular Expressions.
Так и должно быть?
У Васи была проблема с сортировкой электронной почты. Он решил использовать регулярные выражения. Теперь у него 2 проблемы.) Не в упрек регуляркам, просто когда-то улыбнуло).
куча статей про то, как писать регулярки, но ни одной про то, как их потом читать ))
Несколько лет, как для написания и чтения использую сайт https://regex101.com/(есть похожие, мне просто этот понравился). Там и шпаргалка есть и описание введённого выражения и сразу протестировать можно. Но мои выражения были довольно простыми, возможно для сложных случаев не подойдёт.
Все верно, ведь этот вопрос напрямую проистекает из того, как их написать.
Для этого мы можем написать следующее [A-Z,a-z] . Что же это значит? Это значит, что мы указали, что мы хотим выбрать все символы в диапазоне от A до Z (это мы выбираем все заглавные буквы) и, затем, через запятую, мы говорим о том, что хотим выбрать все символы от a до z
Запятая тут не нужна, и даже лишняя. Запятая выберет в тексте собственно запятые, кроме букв, то есть "text,text" будет выбран полностью. Писать надо слитно [A-Za-z]. А ещё есть аналогичный для кириллицы [А-Яа-я], но он не захватывает букву ё, и её надо отдельно указывать: [А-Яа-яЁё].
А ещё в статье не описан наверное самый сложный концепт регулярок, это lazy/greedy квантификаторы. При этом описаны достаточно экзотические lookahead/lookbehind.
Для тестирования регулярных выражений лучше подходит https://regex101.com
Ещё один крутой инструмент для написания, тестирования и разработки регулярных выражений: https://regexr.com/
Пользуюсь только им
Имхо http://regex101.com/ лучше всех
Имхо http://regex101.com/ лучше всех
Существует много сайтов где можно проверить регулярки, а существуют ли сайты с заданиями на эти самые регулярки и проверкой результата? Обучение бы пошло в разы эффективнее
Конкретных сайтов нет. Но можно найти некоторые задания. Например, вот ссылка: http://old.code.mu/tasks/javascript/regular/rabota-s-regulyarnymi-vyrazeniyami-v-javascript-glava-1.html
Там несколько частей, можете просто перейти на след страницу
Много опечаток, а различные примеры в тексте нужно как-то выделять среди обычного текста, t. в конце строки может сбить с толку.
Стоит добавить хотя бы пару конкретных примеров из практики.
И ещё, скрины тяжело читать на мобильной версии, можно сделать скрины менее вытянутыми горизонтально.
и ни слова про ReDoS.
https://en.wikipedia.org/wiki/ReDoS#Evil_regexes
https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
Может так получится что ваша простая регулярка для проверки того же email'а в форме валидации веб приложения, не завершится в обозримом будущем. подвешивая ваше приложение.
на regex101 удобно показывает количество шагов для вычисления регулярки. И есть дебаг вычисления.
20 лет пишу регулярки (т.к поддерживаю несколько проектов на perl, хотя основной язык python) и могу дать один совет, который облегчит восприятие и логику регулярок: не пользутесь фичами с заглядывания вперед/назад. Да, призыв не использовать функционал звучит странно. Но столько людей спотыкаются в них и регулярно обращаются к документации чтобы освежить в памяти именно этот момент.
Чем же их заменить? почти все случаи заменяются на такие приемы:
1) захватить в (блаблаблла) то, что должно присутствовать в тексте и не должно быть изменено, после чего этот же фрагмент вставить в результат как $1 ($2 и тд)
2) использовать [^чего_не_должно_быть]
все это читается на раз-два, в отличие от всяких (?<=Y)X
Согласен. У самого такое было. Про них я написал для того, чтобы было представление о них. Спасибо за совет
А что вы думаете про использование КС грамматик и генераторы парсеров?
(?<!foo)(bar)
без использования lookbehind будет (?:^|[^o]|^o|[^o]o|^oo|[^f]oo)(bar)
.Читается на раз-два?!?
Я же написал "почти все случаи". И перед тем как нажать на сабмит, подумал "но все равно отпишется человек, который найдёт контр пример". Очевидно, что раз фича есть, значит скорее всего от неё будет польза. Мой совет основан на опыте. Причём не только личном. Это и личные обращения" помоги составить регулярку, влом доки читать" и код ревью. Я лишь советую как облегчить себе жизнь. 99% практических регулярок оно покрывает
«но все равно отпишется человек, который найдёт контр пример»
Вы так говорите, как будто я какой-то каверзный редкий случай запостил, а не самый примитивный из возможных пример использования negative lookbehind.
Повторю: я дал совет исходя из своего и опыта коллег. Я и они решали практические задачи. Вот эти сотни практических задач подходят под мой принцип. Если у кого-то много регулярок с отрицаниями, которые надо исключить из поиска, тогда прошу прощения, мой совет не для вас. Но, повторюсь, в большинстве случаев он работает и позволяет не отвлекаться на чтение в доках постоянно забываемой фичи и обнаруживания, что у неё есть свой отдельный синтаксис для (не) жадности
Хорошо, сегодня буду за компом, напишу. С мобилы не очень удобно регулярки писать
Приведу на perl, поскольку (внезапно) на нем лаконичнее. Самое простое, когда необходимо найти фрагмент, перед и/или после которого стоит определенный фрагмент:
$s = "This is a <b>test</b>!";
$s =~ m|<b>(.*?)</b>|;
print $1; # печатает test
Здесь, как я говорил, лучше не использовать сущность "найденный фрагмент" и заглядывания вперед/назад, а проще применить группировку ($1). Пример простой, а вот с заменой немногие, не имея опыта, догадатся сделать так:
# заменим "test" или "bug" на "code" только если впереди стоит фраза
# "this is a " или "that is a "
$s =~ s/(this|that) is a (test|bug)/$1 is a code/;
# или так
$s =~ s/(this is a|that is a) (test|bug)/$1 code/;
# добавим пробелы вокруг text в <любой tag>text</любой tag>
$s =~ s|(<[^>]+>)(.*?)(</[^>]+>)|$1 $2 $3|;
Если человек понимает больше чем час изучения регулярных выражений, во втором примере я ему еще и предложу использовать \1. За "более боевыми" примерами надо лезть в код проектов и находить такие пограниченые варианты, но мне кажется этого итак достаточно, чтобы понять о чем речь. Если кому-то мой вариант менее понятный чем заглядывания - ради бога, я не расстроюсь, что кому-то он не подходит.
Прочитал название, удивился, зашел почитать статью. Увы, это не регулярки проще, это статья для начинающих...
Дело в том, что в основном для новичков и написана статья, так как я сам когда только начал изучать регулярные выражения, мне было очень тяжело и я решил помочь таким людям
Статьи на Хабре не помогли?
Как я и говорил в начале статьи, во время изучения регулярок информация была разбросана везде по частям. Вот я и решил в одну статью вписать основы, которые помогут новичкам лучше разобраться
Самая первая строка в поиске: habr.com/ru/post/545150 (Регулярные выражения (regexp) — основы)
Предельно наглядно для новичка. Настолько наглядно и в одном месте, что ваш материал — шаг назад. Что в ней не было так?
Всё круто, как маленькая придирка - вместо примера с email вначале лучше взять что-нибудь попроще, на тему как правильно валидировать email адреса сломано немало копий, и по факту способа лучше, чем отправить туда письмо - до сих пор никто не придумал.
Осмелюсь предложить ещё regexper.com
Позволяет представлять регулярные выражения в графическом виде. Может быть кому-то пригодится для анализа регулярок, особенно если они написаны не вами и давно. Мне в свое время очень сильно помогло.
Правда, я не помню, все ли функции регулярок он поддерживает. Например, lookahead и lookbehind я не помню точно, так как не сталкивался с ними тогда.
Есть у меня слова и словосочетания (огромное кол-во, порядка 70К). Их нужно удалить из текста в рамках тегов
****
если они там присутствуют. Я так понял нужно использовать знак | Но как…Насколько я понял, нужно удалить слова, которые находятся между тегами? Ну тогда ситуация такая: допустим есть такая вещь: <p>Some text</p>. Получается, что если словосочетание находится между символами > и символом <, то его нужно удалить. Выбрать данное словосочетание можно с помощью ретроспективной и опережающей проверки, про которые я говорил в статье. Если же lookahead не поддерживается, то можно попробовать заменить его. Я просто не знаю подробностей вашего задания. Возможно я неправильно понял описанную вами проблему, но это первое, что мне пришло в голову
Почему бы не использовать полноценный парсер (у вас же что-то вроде HTML) или хотя бы лексер?
Коллега, спасибо за статью!
Обратите внимание, что регулярное выражение - это механизм, который определяет какие последовательности символов входят в язык, а какие - нет. Он изначально не привязан к тексту. Хотя текстовые строки и являются частным случаем строк, с которыми работает регулярка, но также она может быть задана для строк, состоящих из emoji, например, или бинарных символов.
Также коллеги выше правильно заметили, что синтаксис регулярных выражений может меняться в зависимости от имплементации.
Вы можете ознакомиться с курсом "теория автоматов" на edx, там хорошо рассказано про регулярные выражения, на мой взгляд. Кстати, для меня было большим откровением узнать, что конечные автоматы и регулярные выражения - это одно и то же, с точки зрения решаемой задачи.
Сразу дам ссылку на сайт, чтобы вы могли уже писать вместе со мной www.regextester.com
ошибка 503
Я бы ещё про нюансы работы регулярок с многострочным текстом добавил и сделал акцент на регистрозависимость по умолчанию.
Спасибо за статью
Регулярные выражения. Всё проще, чем кажется