Grep Regex 以匹配具有单个顶级域的电子邮件

问题描述 投票:0回答:3

我正在编写一个使用正则表达式匹配电子邮件的 bash 文件。但我只想将电子邮件与单个顶级域匹配,而不是将电子邮件与多个顶级域匹配。

例如那些电子邮件应该匹配:

[email protected]
[email protected]
[email protected]

但这封电子邮件不应该匹配,因为它有 2 个顶级域 .co.fr

[email protected]

我试过以下方法:

grep -E -o '[A-Za-z0-9.]+@[A-Za-z0-9-]+\.[A-Za-z]{2,}(?!\.[A-Za-z])' log.txt > mails.txt

但是

(?!\.[A-Za-z])
部分不适用于 bash,我的理解是,如果它在第一个点之后找到第二个域,它将否定匹配。

当我在在线工具上尝试时它工作正常:https://regex101.com/r/H4ftC3/1

我也试过在最后使用 $ :

[A-Za-z0-9.]+@[A-Za-z0-9-]+\.[A-Za-z]{2,}$
但这个不匹配任何东西。

如何只匹配单个顶级域?

谢谢

regex bash grep regex-negation
3个回答
0
投票

使用

grep

$ grep -E '^\S+@\w+\.\w+$' input_file
[email protected]
[email protected]
[email protected]

查看演示


0
投票

输入文件

$ cat file
[email protected]
[email protected]
[email protected]
[email protected]

grep

grep -vE '@.+\..+\.' file
[email protected]
[email protected]
[email protected]
  • -v
    反转比赛
  • -E
    ERE
    扩展正则表达式

正则表达式匹配如下:

正则表达式 说明
@
按字面匹配字符“@”
.+
匹配除换行符以外的任何字符
在一次和无限次之间,尽可能多的次数,根据需要回馈(贪婪)
\.
匹配字符“.”字面上
.+
见上
\.
匹配字符“.”字面上

0
投票

tl;博士

grep -P -i "[\w+-.]+@[\w+-]+\.[a-z]{2,}$" file.txt 

-P - option for advanced Perl like regex (allows using \w)
-i - ignore case (matches @xyz.com ou @xyz.COM)

对于输入文件:

file.txt

    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]

结果:

    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]
    [email protected]

请不要花哨的字符。

为了回答您的问题,做出一些假设很重要。

  1. 电子邮件 regex 很棘手,您已经在 Stackoverflow (1) 上阅读了这个答案,以及维基百科上的这篇文章 (2)。
  2. 您的电子邮件本地部分(又名用户名)仅包含以下字符:
    A-Za-z
    的字母,
    0
    9
    的数字,特殊字符
    +-_
    (允许的非常减少设置),并在中间点
    .
  3. 没有花哨的
    utf-8
    utf-16
    字符。甚至不是拉丁语(例如
    ç
    ñ

这个假设代表了目前已知的所有电子邮件地址的 99.73%。

允许的字符

username_allowed_chars = [A-Za-z0-9_+-.]

事实上,我假设您使用的是 gnu grep,因此您可以使用

grep -P
(perl 样式正则表达式)和以下集合
\w
等同于
[A-Za-z0-9_]
,因此:

username_allowed_chars = [\w+-.]

对于域部分,删除

+
和点
.
,因此:

domain_allowed_chars = [\w-]

最后,我们将使用

+
进行
1 or more
字符的重复。

grep -P -i "[\w+-.]+@[\w+-]+\.[a-z]{2,}$" file.txt 

我将分解这个正则表达式。首先是广泛使用的字符集

\w

  • \w
    - 翻译 do
    [A-Za-z0-9_]
    word indentifier a.k.a. 用编程术语来说,变量名称允许使用字符。实际上不允许在电子邮件用户名中使用标点符号和其他不寻常的字符;
  • \.
    - 文字点
    .
    ;
  • [\w+-.]+
    - 这些标识符中的一个或多个,并且includes用户名中的perioddot。例如
    [email protected]
    .
  • @
    - 文字
    @
    将用户名与域名分开。
  • [a-z]{2,}$
    - 不少于两个小写字母直到字符串的末尾(用
    $
    标记)。

参考文献

(1) 堆栈溢出

(2) 维基百科

© www.soinside.com 2019 - 2024. All rights reserved.