Как я могу ограничить то, что приходит до и после регулярного выражения - PullRequest
1 голос
/ 24 марта 2020

Мне нужно создать регулярное выражение для идентификации электронных писем. Вот как это выглядит до сих пор:

[A-Za-z0-9]+([._-]*[A-Za-z0-9]+)*[@]+[A-Za-z0-9]+([._-]*[A-Za-z0-9]+)*(.com)*

Что я хочу с этим регулярным выражением, это идентифицировать электронную почту. Дело в том, что электронное письмо не может начинаться или заканчиваться sh какими-либо не alphanumeri c символами. Итак:

.ilikestack@gmail.com or ilikestack@gmail.com_ = invalid
ilike.stack@gmail = valid

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

Ответы [ 2 ]

2 голосов
/ 25 марта 2020

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

Так что, если мы имели регулярное выражение [a-z]+, но мы хотели, чтобы оно совпадало только в том случае, если ему предшествовал только пробел (или в начале файла), а затем только пробел или точка (или конец файла), мы могли Совершенно sh, что следующим образом:

[a-z]+                printf("Successful match: '%s'!\n", yytext);
[^a-z \t\r\n][a-z]+   ;
[a-z]+[^a-z \t\r\n.]  ;
.                     ;

Тогда вход ab cd_ ef. .de fg будет производить вывод:

Successful match: 'ab'!
Successful match: 'ef'!
Successful match: 'fg'!

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

[^ \t\r\nA-Za-z0-9][^ \t\r\n]*   ;
[^ \t\r\n]*[^ \t\r\nA-Za-z0-9.]  ;
0 голосов
/ 24 марта 2020

Довольно хорошо!

Может быть,

(^|\s)[A-Za-z0-9][A-Za-z0-9._-]*@[A-Za-z0-9]+(\s|$)|(^|\s)[A-Za-z0-9][A-Za-z0-9._-]*@[A-Za-z0-9]+\.[A-Za-z]+(\s|$)|(^|\s)[A-Za-z0-9][A-Za-z0-9._-]*@[A-Za-z0-9]+\.[A-Za-z]+\.[A-Za-z]+(\s|$)

Demo 1

или

(^|\s)[A-Za-z0-9][A-Za-z0-9._-]*@([A-Za-z0-9]+|([A-Za-z0-9]+\.[A-Za-z0-9]+)*)(\s|$)

может быть немного ближе.

Если вы хотите sh, чтобы упростить / обновить / изучить выражение, это было объяснено на верхней правой панели regex101.com . Вы можете посмотреть соответствующие шаги или изменить их в этой ссылке отладчика , если вам будет интересно. Отладчик демонстрирует, что движок RegEx может шаг за шагом потреблять некоторые входные строки образца и выполнять процесс сопоставления.

RegEx Circuit

jex.im визуализирует регулярные выражения:

enter image description here


Здесь мы используем квантификатор {2,6}, который ограничивает символы после знака @:

Demo 2

Мы можем заменить это на +, как показано в демонстрации 2. Однако, возможно, это не будет хорошей идеей.


Было бы лучше, если бы вы добавили больше границ к своему выражению, если хотите проверить определенные c типы электронных писем или доменов, например, с помощью

^[A-Za-z0-9][A-Za-z0-9._-]*@[A-Za-z]+\.(?:com|net|org|co)(?:\.uk)?$

В противном случае эти вышеприведенные выражения просто передадут столько строк, не относящихся к электронной почте, как действительный адрес электронной почты.

Demo 3

...