Проверка правильности адреса электронной почты с помощью регулярного выражения в Bash - PullRequest
6 голосов
/ 26 января 2010

Я пытаюсь создать сценарий Bash для проверки правильности адреса электронной почты.

У меня есть это регулярное выражение:

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

Источник: http://www.regular -expressions.info / email.html

А это мой bash-скрипт:

regex=[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

i="test@terra.es"
if [[ $i=~$regex ]] ; then
    echo "OK"
else
    echo "not OK"
fi

Сценарий завершается ошибкой и выдает мне следующее:

10: синтаксическая ошибка: EOF в подстановке обратной кавычки

Любая подсказка ??

Ответы [ 8 ]

9 голосов
/ 26 января 2010

У вас есть несколько проблем:

  • Регулярное выражение должно быть заключено в кавычки и экранированы специальные символы.
  • Регулярное выражение должно быть закреплено (^ и $).
  • ?: не поддерживается и должен быть удален.
  • Требуется пробел вокруг оператора =~.

Конечный продукт:

regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"

i="test@terra.es"
if [[ $i =~ $regex ]] ; then
    echo "OK"
else
    echo "not OK"
fi
7 голосов
/ 26 января 2010

Вам не нужно создавать такое сложное регулярное выражение для проверки действительной электронной почты. Вы можете просто разделить на «@», а затем проверить, есть ли 2 элемента, один перед @, а другой сзади.

i="test@terraes"
IFS="@"
set -- $i
if [ "${#@}" -ne 2 ];then
    echo "invalid email"
fi
domain="$2"
dig $domain | grep "ANSWER: 0" 1>/dev/null && echo "domain not ok"

Для дальнейшей проверки домена вы можете использовать такие инструменты, как dig, чтобы запросить домен. Это лучше, чем регулярное выражение, потому что @ new.jersey сопоставляется с регулярным выражением, но на самом деле это не правильный домен.

5 голосов
/ 26 января 2010

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

Я бы порекомендовал использовать более простое регулярное выражение, такое как .*@.*, потому что вся сложность бесполезна. foo@example.com выглядит прекрасно и будет приниматься любым регулярным выражением, но все же его не существует.

1 голос
/ 19 апреля 2011

Bash версия менее 3.2:

if [[ "$email" =~ "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$" ]]
then
    echo "Email address $email is valid."
else
    echo "Email address $email is invalid."
fi

Версия Bash больше или равна 3,2 :

if [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]
then
    echo "Email address $email is valid."
else
    echo "Email address $email is invalid."
fi

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

0 голосов
/ 30 марта 2016

Опоздал на вечеринку, но я адаптировал скрипт для чтения файла, содержащего электронные письма, и его фильтрации с использованием регулярных выражений RFC822, списков опечаток домена, поиска mx (благодаря eagle1 здесь) и неоднозначной фильтрации электронной почты.

Скрипт можно использовать как:

./emailCheck.sh /path/to/emailList

и создает два файла: отфильтрованный список и неоднозначный список. Оба они уже очищены от адресов, не соответствующих RFC822, доменов электронной почты, которые не имеют действительных доменов MX, и опечаток домена.

Сценарий можно найти здесь: https://github.com/deajan/linuxscripts

Исправления и комментарии приветствуются:)

0 голосов
/ 27 марта 2014

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

#!/bin/bash
#Regexp
regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"

#Vars
checkdig=0;
checkreg=0;
address=$1;
maildomain=`echo $address | awk 'BEGIN { FS = "@" } ; { print $2 }'`;

#Domain Check
checkdns() {
        echo $maildomain | awk 'BEGIN { FS = "@" } ; { print $2 }' | xargs dig $maildomain | grep "ANSWER: 0" 1>/dev/null  || checkdig=1;
}

#Regexp
checkreg() {
        if [[ $address =~ $regex ]] ;
                then checkreg=1;
        fi
}

#Execute
checkreg;
checkdns;

#Results
if [ $checkreg == 1 ] && [ $checkdig == 1 ];
        then    echo "OK";
        else    echo "not OK";
fi
#End

Ничего особенного.

0 голосов
/ 19 апреля 2011

Однажды в момент безумия я написал эту подпрограмму Perl на основе книги «Освоение регулярных выражений»:

sub getRFC822AddressSpec
{
    my ($esc, $space, $tab, $period) = ('\\\\', '\040', '\t', '\.');
    my ($lBr, $rBr, $lPa, $rPa)      = ('\[', '\]', '\(', '\)');
    my ($nonAscii, $ctrl, $CRlist)   = ('\200-\377', '\000-\037', '\n\015');

    my $qtext       = qq{ [^$esc$nonAscii$CRlist] }; # within "..."
    my $dtext       = qq{ [^$esc$nonAscii$CRlist$lBr$rBr] }; # within [...]
    my $ctext       = qq{ [^$esc$nonAscii$CRlist()] }; # within (...)
    my $quoted_pair = qq{ $esc [^$nonAscii] }; # an escaped char
    my $atom_char   = qq{ [^()$space<>\@,;:".$esc$lBr$rBr$ctrl$nonAscii] };
    my $atom        = qq{ $atom_char+     # some atom chars
                          (?!$atom_char)  # NOT followed by part of an atom
                        };
    # rfc822 comments are (enclosed (in parentheses) like this)
    my $cNested     = qq{ $lPa (?: $ctext | $quoted_pair )* $rPa };
    my $comment     = qq{ $lPa (?: $ctext | $quoted_pair | $cNested )* $rPa };

    # whitespace and comments may be scattered liberally
    my $X           = qq{ (?: [$space$tab] | $comment )* };

    my $quoted_str  = qq{ " (?: $qtext | $quoted_pair )* " };
    my $word        = qq{ (?: $atom | $quoted_str ) };
    my $domain_ref  = $atom;
    my $domain_lit  = qq{ $lBr (?: $dtext | $quoted_pair )* $rBr };
    my $sub_domain  = qq{ (?: $domain_ref | $domain_lit ) };
    my $domain      = qq{ $sub_domain (?: $X $period $X $sub_domain )* };
    my $local_part  = qq{ $word (?: $X $period $X $word )* };
    my $addr_spec   = qq{ $local_part $X \@ $X $domain };

    # return a regular expression object
    return qr{$addr_spec}ox;
}

my $spec = getRFC822AddressSpec();
my $address = q{foo (Mr. John Foo) @ bar. example};
print "$address is an email address" if ($address =~ qr{$spec});
0 голосов
/ 26 января 2010

Непосредственная проблема с вашим скриптом в том, что вам нужно исправить цитату:

regex='[a-z0-9!#$%&'"'"'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'"'"'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?'

Однако это регулярное выражение не принимает все синтаксически допустимые адреса электронной почты. Даже если это так, не все синтаксически действительные адреса электронной почты доставляются.

Если доставляемые адреса - это то, что вас волнует, не беспокойтесь о регулярном выражении или другом способе проверки синтаксиса: отправьте запрос по адресу, который предоставляет пользователь. Будьте осторожны, чтобы не использовать ненадежный ввод как часть вызова команды! С sendmail запустите sendmail -oi -t и напишите сообщение на стандартный ввод процесса sendmail, например ,

To: test@terra.es.invalid
From: no-reply@your.organization.invalid
Subject: email address confirmation

To confirm your address, please visit the following link:

http://www.your.organization.invalid/verify/1a456fadef213443
...