Разрешить + в регулярном выражении - PullRequest
5 голосов
/ 31 марта 2011

Regex поражает меня.Как я могу изменить это, чтобы проверять электронную почту со знаком плюс?так что я могу зарегистрироваться с test+spam@gmail.com

if(!preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$/i", $_GET['em'])) {

Ответы [ 5 ]

33 голосов
/ 31 марта 2011

Похоже, вы на самом деле не знакомы с тем, что делает ваше регулярное выражение в настоящее время, что было бы хорошим первым шагом перед его изменением.Давайте пройдемся по вашему регулярному выражению, используя адрес электронной почты john.robert.smith@mail.com (в каждом разделе ниже выделенная жирным шрифтом часть соответствует этому разделу):

  1. ^ - это начало привязки строки .Он указывает, что любое совпадение должно начинаться с начала строки.Если шаблон не привязан, механизм регулярных выражений может соответствовать подстроке, что часто нежелательно.

    Якоря имеют нулевую ширину, что означает, что они не захватывают никаких символов.

  2. [_a-z0-9-]+ состоит из двух элементов: класс символов и модификатор повторения :

    • [...] определяет класс символов,который сообщает движку регулярных выражений, любой из этих символов является действительным совпадением .В этом случае класс содержит символы az, цифры 0-9 и тире и подчеркивание (обычно тире в классе символов определяет диапазон, поэтому вы можете использовать a-z вместо abcdefghijklmnopqrstuvwxyz; если задано какпоследний символ в классе, он действует как буквальный тире).
    • + - модификатор повторения, который указывает, что предыдущий токен (в данном случае, класс символов) может повторяться один или несколько раз.Есть два других оператора повторения: * соответствует нулю или более раз;? соответствует ровно нулю или одному разу (т. Е. Делает что-то необязательно ).

    (захватывает john.robert.smith@mail.com)

  3. (\.[_a-z0-9-]+)* снова содержит класс повторяющихся символов.Он также содержит группу и экранированный символ:

    • (...) определяет группу, которая позволяет группировать несколько токенов вместе (в этом случае группа будетповторяется в целом).
      Допустим, мы хотели сопоставить 'abc', ноль или более раз (т. е. abcabcabc соответствует, abcccc нет).Если мы попытаемся использовать шаблон abc*, модификатор повторения будет применяться только к c, потому что c - это последний токен перед модификатором.Чтобы обойти это, мы можем сгруппировать abc ((abc)*), в этом случае модификатор будет применяться ко всей группе, как если бы это был один токен.
    • \. указывает буквальную точкуперсонаж.Причина, по которой это необходимо, заключается в том, что . - это специальный символ в регулярном выражении, означающий любой символ .Поскольку мы хотим сопоставить действительный символ точки, нам нужно его избежать.

    (захватывает john.robert.smith@mail.com)

  4. @ не является специальным символом в регулярном выражении, поэтому, как и все другие не специальные символы, он соответствует буквально.
    (захватывает john.robert.smith @ mail.com)

  5. [a-z0-9-]+ снова определяет класс повторяющихся символов, как пункт № 2 выше.
    (захватывает john.robert.smith@mail.com)

  6. (\.[a-z0-9-]+)* - это почти тот же шаблон, что и № 3 выше.
    (захватывает john.robert.smith@mail.com)

  7. $ - конец привязки строки.Он работает так же, как ^ выше, за исключением совпадений с концом строки.


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

(\+[a-z0-9-]+)?

При вставке в регулярное выражение это будет выглядеть так:

/^[_a-z0-9-]+(\.[_a-z0-9-]+)*(\+[a-z0-9-]+)?@[a-z0-9-]+(\.[a-z0-9-]+)*$/i
7 голосов
/ 31 марта 2011

Сохрани свое здравомыслие. Получить готовый PHP RFC 822 Анализатор адресов электронной почты

1 голос
/ 31 марта 2011

\+ будет соответствовать буквальному +, но имейте в виду: вы все равно не сможете подобрать все возможные адреса электронной почты в соответствии со спецификацией RFC, потому что фактическое регулярное выражение для этого - безумие ,Это почти наверняка не стоит того;Вы должны использовать настоящий парсер электронной почты для этого.

1 голос
/ 31 марта 2011

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

/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
0 голосов
/ 28 июля 2012

Это еще одно решение (аналогично решению, найденному Дэвидом):

//Escaped for .Net
^[_a-zA-Z0-9-]+((\\.[_a-zA-Z0-9-]+)*|(\\+[_a-zA-Z0-9-]+)*)*@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*(\\.[a-zA-Z]{2,4})$

//Native
^[_a-zA-Z0-9-]+((\.[_a-zA-Z0-9-]+)*|(\+[_a-zA-Z0-9-]+)*)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,4})$
...