Как стать автором
Обновить

Комментарии 34

Символ латыни - это примерно как цифры математики, лучше или латинский алфавит или латиница, кроме этого, \s - это не только пробел, а все пробельные сущности и их несколько. Время от времени приходиться использовать сложные регулярки (если что, я не программист) для поисков в текстах, html, коде и т.п. поэтому пришлось разобраться с этим, но помню время, когда это все выглядело как китайская грамота)). А еще есть онлайн сервисы, которые помогают сэкономить время типа regex101.com, может кому-то ссылка пригодится

Спасибо за подробный разбор. regex101.com уже был указан в разделе "Ссылки".

Вот это серьезная неточность:

  • \s ≡ [ ] – исключительно пробел

Как сказано выше, это все пробельные символы (табуляции, всякие хитрые пробелы из юникода и тд.). Поправьте, пожалуйста.

Вопрос по пятому совету по оптимизации: каким образом экранирование может влиять на скорость выполнения?

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

При добавлении лишнего экранирования будет — на наносекунды — замедлена компиляция регулярного выражения в процессе создания объекта Regex. Но время обработки анализируемой строки методами Regex никак не изменится.

Отлично! Я бы ещё в советы добавила "Именуйте группы, пожалуйста". Это очень упрощает дальнейший разбор. Самим же потом вспоминать "а что я тут имел ввиду?". Особенно когда регулярка выглядит как забор.

Регулярки отлично подходят для единоразовых скриптов, но в production-ready коде что-то сложнее пяти символов является потенциальной проблемой. Их сложно читать, в них сложно искать ошибки, они могут интерпретироваться немного по-разному, у них разная поддержка юникода.

Если задача хорошо решается без них, то лучше их не использовать. В ином случае -- обязательно покрывать тестами.

Можно посмотреть, как выглядят регулярные выражения для телефонов разных стран. Можете ли вы легко понять формат индийских номеров?

(\+*)((0[ -]+)*|(91 )*)(\d{12}+|\d{10}+))|\d{5}([- ]*)\d{6}

А регулярка для email даже имеет свой сайт.

Для этих целей можно использовать построитель регулярных выражений с человеческим видом, например https://github.com/bcwood/FluentRegex

Я в python использую флаг re.VERBOSE, что позволяет писать регулярку в несколько строк, добавлять комменты и пр.

# Stupid demo. Same as re.compile(r"\d+\.\d*")
a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.VERBOSE)

исправьте, пожалуйста, ошибку:

для выражения [0-9]* "abs" тоже позитивный результат

У вас ошибка в примерах в разделе «Разбор базового синтаксиса».
Для регулярного выражения \+7 значение “++7” будет позитивным, а не негативным результатом.
И в примерах с длинами условий тоже ошибки:
для выражения [0-9] {3} строка “5123” и для выражения [0-9] {3,5} строка “125123” дадут позитивный результат

Данные примеры больше для понимания разработчиков уровня Junior, понятно что для полного правильного кейса стоит использовать ^\+7$. При таком паттерне мой пример будет корректный, но всё таки это больше статья для начинающих поэтому не стоит усложнять примеры)

У вас в примерах есть значения как с явным указанием начала строки, так и без него. Значит вы хотели продемонстрировать разницу. Делать это, приводя некорректные примеры очень плохо. Особенно для разработчиков уровня Junior. Это опытные разработчики поймут, что вы ошиблись, а новички зависнут в попытке понять почему должен получится такой результат. И хорошо еще, если они догадаются запустить код и проверить…

про greedy/lazy ни слова? значит, скоро познакомитесь через новые седины

и не забываем классиков:
> Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

НЛО прилетело и опубликовало эту надпись здесь

А в чем смысл делать английский заголовок для русской статьи?

t=20181125T142800&s=850.12&fn=8715000100011785&i=86841&fp=1440325305&n=1

Это как раз неудачный пример для парсинга регулярками. А что вы будете делать, если порядок параметров изменится? Тут логичней было бы дробить строку сплитом сначала по &, потом по =, далее определять имя параметра и парсить его значение стандартными методами. Т.е. тут вообще можно без регулярок обойтись.


Хорошие практики и советы по оптимизации

Еще забыли: если можете обойтись без регулярок — не используйте их. А также имейте представление о контекстно-свободных парсерах.

Еще забыли: если можете обойтись без регулярок — не используйте их.

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

Нельзя с этим согласиться.

Если какую-то проблему можно решить регуляркой, то почему бы это не сделать?
Принимать решение исключительно "так я могу это сделать и без регулярки, значит не буду пользоваться" - это не аргумент.
Регулярка - просто инструмент. И если он где-то упрощает жизнь - то пользуйтесь.

Если какую-то проблему можно решить регуляркой, то почему бы это не сделать?

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

И если он где-то упрощает жизнь - то пользуйтесь.

Да пользуюсь, пользуюсь. :) До сих пор горжусь арканными заклинаниями (то, что получилось, иначе не назовёшь), которые написал на прошлой работе для чтения и редактирования легаси-конфиг-файлов на перле (когда конфиг это код на языке перл, и уже никто не расскажет, почему). Надеюсь, что те, кто сейчас поддерживает этот код, не знают, где я живу.

Вы всегда легко можете посчитать сложность Вашей регулярки?

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

Ещё большая неудачность примера в в том, что формат разбираемой строки — это передача параметров в GET-запросе и в одном из типов POST-запроса. Для разбора которых в языке, ориентированном на web (если не в «голом» C#, то в ASP.NET), ожидаешь увидеть готовый метод распаковки строки в ассоциативный массив или структуру.

Например, в PHP это функция parse_str.

Да. А в python это urllib.parse.parse_qs() и urllib.parse.parse_qsl()

Паттерн ^(?:8|+7)[0-9]{10}$

В ваш паттерн российских номеров совершенно случайно попал весь Казахстан.

[0-6,8,9]{10} будет чуть точнее.

В российских номерах не бывает семёрок?

Действительно - это было 'сильно' с моей стороны.

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

В мобильных сетях нумерация 77\d{9} пока полностью за Казахстаном. Изначальный смысл комментария был в этом.

Принципы и идеи, заложенные в его работах, были практически реализованы Кеном Томпсоном и с его лёгкой руки проникли в язык Perl.

Насколько я знаю, Кен был тем, кто реализовал их в ed, grep и др.

А в Perl они были впервые реализованы уже в самом языке, а не при помощи внешней библиотеки. И Гвидо реализовал гораздо больше, чем было в изначальных extended regexp.
И уже после Perl появилась свободная библиотека PCRE, на базе которой регулярки появились в других языках.

– означает что предыдущее условие до данного символа, может встречаться один или несколько раз или вовсе не будет (соответственно может повторятся)

Какой-то странный перевод. Что такое "условие" неоднозначно. Было бы лучше пояснить правильную терминологию - что такое мета-символ, что такое якорь, что такое квантификатор. А тут, как в очень многих других "не очень" инструкциях, просто вываливают какое-то количество знаков, которое нужно заучить наизусть.

Уж проще почитать справку на regex101

Помню в середине 90-х, когда B-деревья были большими, мне потребовалось реализовать что-то типа сопоставления с образцом на Borland C++ 3.1 под DOS на 80286-м. Интернета еще не было не у всех не, я не знал, что «все уже украдено до нас», и поэтому по сути пришлось изобретать регулярные выражения (с упрощенным и извращенным синтаксисом, естественно). Через несколько лет интернет завезли, и я узнал о PCRE. И мне даже удалось ее скомпилировать в BC3.1! Правда, там было несколько десятков тысяч строк кода, и размер получавшегося exe-шника не лез ни в какие ворота (да и компилировалось оно добрых минут 20 на 80286, постоянно упираясь в память), так что дальше забавного эксперимента это никуда не пошло.

\w ≡ [a-zA-Z0-9_] – любой символ латыни, все числа и _

В общем случае это неверно.

\w - это Символ «слова». В зависимости от реализации это может быть не только латиница. В python3 например, в эту маску попадут и символы национальных алфавитов.

Допишите, пожалуйста, пример про экранирование спец. символа

>> \ – экранирование любого спец. символа

По-моему в примере ^\+7\d{10} вариант +712345678900 это не позитивный результат, поскольку после +7 идет 11 цифр. Вероятно это просто опечатка но немного вводит в заблуждение касательно терминов позитивный и негативный результат. 

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории