Pull to refresh

Comments 55

Очень подробная статья и много примеров, да еще и все в одном месте, спасибо. Для новичка действительно может быть полезным стартом.
Не надо регулярно выражаться при самых маленьких.
Мы выбираем все, что не пробел (потому что первая часть email может содержать любой набор символов)
… включая пробел.
"name with spaces"@example.com
Вообще, imho не надо учить новичков проверять email regexp-ами.
Да, Вы совершенно правы, спасибо. В таком случае имя пользователя должен находиться в кавычках, насколько я помню. С этим примером наша регулярка не справится.

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

В дальнейшем, конечно, такие вещи, как работа с email или URL стоит гуглить, интересоваться стандартами и типовыми решениями.
Понятно, что это лишь пример. Просто новички часто берут примеры сразу в работу, не читая особо текст с предупреждениями о RFC и т.п… Случай email вообще — особенный. Казалось бы он достаточно нагляден, но
В дальнейшем, конечно, такие вещи, как работа с email или URL стоит гуглить, интересоваться стандартами и типовыми решениями.
А правильные типовые решения скорее всего такие:
Невозможно проверить адрес e-mail на допустимость с помощью регулярных выражений
или
Прекратите проверять Email с помощью регулярных выражений!
Раз уж завязалась дискуссия, стоит определиться с целью, которую мы преследуем, проверяя email.

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

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

Тот же Gmail не даст так просто зарегистрировать email с пробелом, вот его сообщение об ошибке:
Некорректное имя почтового ящика. Допустимо использовать только латинские буквы, цифры,
знак подчеркивания («_»), точку («.»), минус («-»)


А вот ответ Yandex:
Логин может состоять из латинских символов, цифр, одинарного дефиса или точки. Он должен начинаться с буквы, заканчиваться буквой или цифрой и содержать не более 30 символов.


Ответ Mail:
Некорректное имя почтового ящика. Допустимо использовать только латинские буквы, цифры,
знак подчеркивания («_»), точку («.»), минус («-»)


Ответ Yahoo:
Имя пользователя может содержать только буквы, цифры, точки (.) и символы подчеркивания (_).


Даже если к нам придет пользователь с некорректным email, который он себе как-то сделал, мы напишем ему, что следует завести другой email ради нашего сервиса. Но это менее 0.(0)1%.

Зато мы заранее предупредим остальных 99.(9)% пользователей о возможной опечатке, чтобы им не пришлось проходить этап регистрации дважды.

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

Вы в статье рассматриваете абстрактные примеры валидации email, и именно в этом абстрактном контексте я и беседую. Поэтому не надо в рамках данной дискуссии подменять абстрактную задачу на какую-то конкретную.

Поясню. Примеры с Яндексом и т.д. совсем не в тему. Это примеры систем со своими требованиями и ограничениями к формату email адреса и именно эти свои требования они проверяют. Это пример как раз конкретной задачи с определенными ограничениями.

Поэтому если бы в вашей статье пример выглядел так:
«Давайте проверим email пользователя Яндекс — логин может состоять из латинских символов, цифр, одинарного дефиса или точки. Он должен начинаться с буквы, заканчиваться буквой или цифрой и содержать не более 30 символов.»
то мне был бы понятен ваш аргумент, однако в таком случае и этой дискуссии бы не было.

Вы же в статье пишите о RFC
На самом деле есть RFC, который определяет правильность email. И есть “регулярки” по RFC — вот примеры.
и якобы (примеры по ссылке — тоже работают неправильно) существующей возможности проверки email адреса регулярным выражением. Без какой-то конкретики о постановке задачи. Абстрактно. Я вам указал на то, что это — ошибка и что тему «валидация email регулярным выражением» было бы правильно пометить в главу «Какие задачи не решаются регулярными выражениями».
Соглашусь. В конечном итоге Вы все равно правы.
Еще раз спасибо за дополнение. :)
Можно, все верно. :)
Но тогда не удалось бы раскрыть в примере различные способы работы выражений.
Нет, Виталий, нельзя :) Я подумал, что это шутка была.

Если речь идет о валидации — условно можно.
С регуляркой из вашей статьи мы можем ошибиться с проверкой и отсечь верный email. Не особо страшно, тем более, что этот адрес будет достаточно экзотический.
С этой регуляркой мы почти все неверные адреса считаем верными. На мой взгляд такой подход — хуже.

Ну а если речь идет о поиске в тексте (как в вашей статье) — эта регулярка совсем не годится.

Наверно мы тогда о разных вещах говорили. Спасибо за дополнение.

Каждый раз глядя на своё программное решение с регулярными выражениями для разбора строк, чувствую, что единственное полезное выражение это «что-то (\d+)» и ничего другого лучше не писать.

Очень сложно поддерживать регулярные выражения в программе, всегда в первоначальный «простой» вариант вносятся изменения и усовершенствования. В итоге получается мини-монстр.
Как ящик пандоры — такие надежды всегда, а получается не совсем то.

На мой взгляд сама история появления регулярных выражений определяет их пределы использования. Они же родились в научной среде как некое теоретическое изыскание вылившееся в такой вот язык (утрирую конечно) и на практике оно впервые появилось в текстовом редакторе, чтобы можно было делать более сложные текстовые замены. И это стихия регулярных выражений.
Ты сделал замену регулярным выражением и сразу оценил результат, если он тебя устроил то регулярное выражение может кануть в забытие, т.к. оно выполнило свою роль. Это действительно бывает полезно.
В одной старой шутке говорится: если у вас есть проблема, и вы собираетесь решать ее с использованием регулярных выражений, то у вас есть две проблемы.
UFO just landed and posted this here
Вообще я имел ввиду, что это нифига не шутка, а суровая правда жизни, а вовсе не просил рассказать мне эту шутку :)
Мне кажется, что главное все делать аккуратно.
Если приходится использоваться регулярку, ее стоит выносить в переменную с человеко-понятным названием. Желательно еще где-то рядом (в комментарии или документации) иметь пример текста, для которого регулярка должно работать верно.
И тогда жить станет чуточку проще, особенно тем, кто будет работать с кодом после.
UFO just landed and posted this here
Определить, используя регулярные выражения?
Задачу можно решить через инкремент/декремент целого числа, если на выходе не равно нулю, то скобки несбалансированы. Случаи, когда закрывающая идёт раньше открывающей, обрабатывается условием, что декрементировать 0 нельзя.
В случае одного вида скобок — да это будет супер элегантным решением.
Если несколько видов скобок, то по вашему алгоритму пройдет конструкция ( [ ) ], хотя она несбалансированая.
Если видов скобок несколько, то, естественно, алгоритм не сработает.

Но в комментарии стояла задача найти
все фигурные скобки в тексте
, т.е. только '{' и '}'.

Для разных видов скобок будет полезно применить стек, в который помещать открывающие скобки. При закрытии соответствующей скобки вынимать ее из стека. Выдавать ошибку, если закрывается не та скобка, которая верхняя в стеке.

UFO just landed and posted this here
Это не очень удачное направление. Регулярные выражения (если не рассматривать некоторые расширения) непригодны для нормальной обработки рекурсивно вложенных структур.
Если с ходу сложно вспомнить регулярки (а я всегда перед их использованием гуглю), то на собеседовании нужно было переключиться на другой способ решения и попробовать его. Важен не только конечный решенный вариант, но поведение при сложностях с задачей.
UFO just landed and posted this here
Да и не новичкам, я вам скажу. Стыдно признаться, но я никак не могу освоить эту технику. ;-) Хотя такие потребности возникают время от времени

Задачи со скобками как правило решаются с помощью стека же

Все дальнейшие примеры предлагаю смотреть в https://regex101.com/.
Два аргумента за использование regexr.com
1. На теле по ошибке добавить p — попадёшь на вирусняк с редиректом
2. Не работает в FF с выключенным параметром dom.workers.enabled (как и приват в avito)
[password|пароль]

Неправильная регулярка. Квадратные скобки должны быть заменены на круглые.
>['password', 'пароль', 'passwпароль', 'рольпа', 'drowssap'].map(w => /[password|пароль]/.test(w));
Array [ true, true, true, true, true ]
Верно, спасибо! Исправлено.
1. Регулярные выражения надо знать.
2.
Some people, when confronted with a problem, think «I know, I'll use regular expressions.» Now they have two problems.

--Jamie Zawinsk
Некоторые люди во время решения некой проблемы думают: «Почему бы мне не использовать регулярные выражения?». После этого у них уже две проблемы…
Jamie Zawinski
Когда-то на хабре видел статью про билибиотеку, строющую регулярные выражения из вызовов вроде regexp=new RegExp().startsWith(«aaa»).oneOf(«bbb»,«ccc»).oneOrMore(digit).endsWith(endOfLine);
Но не могу теперь найти. Кто помнит, как она называлась?
Спасибо. Да, я писал, что буква “ё” не входит в диапазон [а-я].

C кириллицей указанный диапазон работает по-разному для разных кодировок. В юникоде, например, в этот диапазон не входит буква “ё”. Подробнее об этом тут.
UFO just landed and posted this here
Да, это особенность JS:
The RegExp object keeps track of the lastIndex where a match occurred, so on subsequent matches it will start from the last used index, instead of 0.


Спасибо, интересный момент.

Обращение к таким регуляркам лучше делать через getter, в котором обнулять lastIndex перед выдачей. Таким образом они всегда будут "чистыми".

Конечно, если lastIndex не планируется использовать как-то еще. Его же не зря придумали. :)
Для начала: спасибо за подробную статью, сохраню, чтобы выдавать интересующимся для ознакомления.

Позволю себе только немного уточнить (здесь, т.к. это как раз может повлиять на новичков, которые часто берут примеры сразу в работу):
Но если мы укажем регулярное выражение “/\d/”, то нам вернётся только первая цифра. Мы, конечно, можем использовать модификатор “i”...

Видимо модификатор: «g»?

Или задать “от” и “до”, указав вот так: “{N, M}”.

Которые также можно задавать по отдельности вида “{N,}” или “{,M}”. Тоже полезная функция.

И ещё я бы упомянул про пассивные группы "(?:test)", которые не попадают в результат позволяют ограничить его только искомыми «полезными» группами.

Ну и мне очень часто помогает вот этот файлик.
Спасибо. Про «g» исправил. Поспешил, видимо, когда писал.

Остальное — тоже полезное дополнение. Нарушать структуру повествования уже поздно, но тут они будут ждать своего внимательного читателя. :)

ololo@mail.ru — хозяину этого адреса сейчас икаеться, наверно. А статья годная, спасибо.

Да, стоило быть избирательнее. Вдруг человек этот email использует для бизнеса.
Исправил, спасибо!
Спасибо, как начинающему front-end`у — отличное пособие!
Рад, что статья оказалось полезной. :)
[http|https] и http[s] не эквиваленты. Наверное, Вы хотели написать (http|https).
Верно, спасибо! Исправлено.
На самом деле не первая моя ошибка подобного рода — не могу избавиться от мысли, что знак или "|" должен работать без захвата тоже, с символами "[" и "]". :(
Не уверен, что до конца понимаю, почему это не так…
Sign up to leave a comment.