Я хочу создать регулярное выражение в Ruby, чтобы ограничить ввод электронной почты следующими правилами:

[имя пользователя]@[имя домена].[имя домена верхнего уровня]

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

  2. Имя пользователя должно содержать хотя бы одну английскую букву.

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

  4. Доменное имя верхнего уровня может содержать только английские буквы, цифры и дефисы. Должен заканчиваться английской буквой.

  5. Имя домена и имя домена верхнего уровня должны быть разделены точками, а электронное письмо должно содержать как минимум 1 имя домена верхнего уровня.

Вот мое регулярное выражение:

/\A[a-zA-Z0-9]((?!\.\.)(?!\+\+)[\w\-+.])*[\w\-]@[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]*)+[a-zA-Z]\z/

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

-1
fanfan 2 Фев 2022 в 18:58
2
Почему вы хотите ограничить электронные письма этими правилами? Почему бы вам просто не разрешить все действительные адреса электронной почты?
 – 
spickermann
2 Фев 2022 в 21:20
На самом деле я думал, что эти ограничения и есть действующая электронная почта. Существуют ли какие-либо официальные стандарты электронной почты, которым нужно следовать?
 – 
fanfan
5 Фев 2022 в 15:21

4 ответа

Да, наверное, это не совсем то, что вы хотели :)

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

Ограничивая регулярное выражение, вы создаете неудобства для своих пользователей.

Поэтому я считаю, что основным критерием является наличие @. Если это действительный адрес электронной почты, то пользователь получит электронную почту. Если нет, то и не будет. Это довольно просто :)

Единственный способ проверить электронную почту — отправить сообщение и получить подтверждение.

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

https://emailregex.com/#crayon-5dcf0d9dc15ec916764848

Или вы можете использовать встроенное регулярное выражение Ruby, просто вызовите константу

URI::MailTo::EMAIL_REGEXP

Но, возможно, достаточно просто @

2
mechnicov 2 Фев 2022 в 19:38

На самом деле вы хотели бы получить здесь что-то вроде условия "и": часть перед @ может включать только некоторые допустимые символы И должна содержать определенные символы в конце в то же время.

С помощью регулярных выражений способ моделирования — это позитивный взгляд вперед:

s1 = "123@foo.bar"
s2 = "a123@foo.bar"
s3 = "123a@foo.bar"

s1.match?(/(?=[a-zA-Z])\w+@/) # => false
s2.match?(/(?=[a-zA-Z])\w+@/) # => true
s3.match?(/(?=[a-zA-Z])\w+@/) # => true

Я значительно упростил шаблон для простоты, но здесь важна часть (?=[a-zA-Z]) — мы проверяем, есть ли хотя бы одна буква перед @, не «потребляя» входной поток, чтобы следующий шаблон мог проверять начиная с той же позиции...

1
Konstantin Strukov 2 Фев 2022 в 19:34

Действительный адрес электронной почты может сильно отличаться от того, что вы описали. Локальная часть перед @ может также включать все эти символы: !#$%&'*+-/=?^_``{|}~. Или вместо домена может быть просто IP-адрес после @. И имейте в виду, что домены не обязательно должны включать .. А как насчет 我買@屋企.香港? Да, это действительный адрес электронной почты, разрешенный RFC 6530. Вы найдете другие удивительные примеры адресов электронной почты в Википедии: Адрес электронной почты.

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

Поэтому я предлагаю более простое регулярное выражение: \A.+@.+\z, а затем прошу пользователя подтвердить свой адрес электронной почты. Или вы можете просто захотеть использовать регулярное выражение, которое поставляется с Ruby (URI::MailTo::EMAIL_REGEXP) или с Devise (Devise.email_regexp), когда вы его используете.

1
spickermann 26 Мар 2022 в 09:23

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

\A(?=[^@]*[a-z])(?![^@]*(?:\+\.|\.\+))[a-z\d+_.-]+@[a-z\d-]+\.[a-z\d-]*[a-z]\z

Демонстрация Rubular<¯\(ツ)< /em>/¯>демонстрация PCRE

Я включил демонстрацию PCRE (на regex101.com), потому что по этой ссылке можно найти значительно больше информации. (Для этого регулярного выражения механизм PCRE совместим с Ruby.) Например, наведите курсор на каждую часть регулярного выражения в ссылке PCRE, и вам будет предоставлено объяснение его функции.

Обратите внимание, что в обеих ссылках я заменил начало и конец привязки строки (\A и \z) привязкой к началу и концу строки (^ и &), и заменили [^@] на [^@\n], чтобы продемонстрировать регулярное выражение для различных строк, причем допустима только первая.

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

\A           # match beginning of string
(?=          # begin a positive lookahead
  [^@]*      # match zero or more chars other than '@'
  [a-z]      # match a letter
)            # end positive lookahead
(?!          # begin negative look-ahead
  [^@]*      # match zero or more chars other than '@'
  (?:        # begin non-capture group
    \+\.     # match '+.'
  |          # or
    \.\+     # match '.+'
  )          # end non-capture group
)            # end negative lookahead
[a-z\d+_.-]+ # match one or more chars from char class
@            # match '@'
[a-z\d-]+    # match one or more chars from char class
\.           # match '.'
[a-z\d-]*    # match zero or more chars from the char class
[a-z]        # match a letter
\z           # match end of string
/ix          # invoke case-indifferent and free-spacing modes
0
Cary Swoveland 3 Фев 2022 в 01:59