You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Bash的Grep正则匹配仅含单个顶级域名的邮箱

匹配仅含单个顶级域名的邮箱

问题根源

你使用的grep -E采用POSIX扩展正则标准,不支持负前瞻这类Perl兼容正则(PCRE)特性;而添加$的正则仅能匹配行尾的邮箱,若日志中邮箱后还有其他内容就无法命中。

解决方案1:使用grep的PCRE模式(推荐)

大部分GNU grep支持-P选项启用PCRE,直接复用你原本的正则即可生效:

grep -P -o '[A-Za-z0-9.]+@[A-Za-z0-9-]+\.[A-Za-z]{2,}(?!\.[A-Za-z])' log.txt > mails.txt
  • -P:启用Perl兼容正则,让负前瞻(?!\.[A-Za-z])生效,确保顶级域名后不会出现.字母的多级域名结构
  • -o:仅输出匹配到的邮箱部分,无需依赖行尾位置

解决方案2:无PCRE支持时的替代方案(awk实现)

如果你的系统不支持grep -P(如部分BSD系统),可以用awk先匹配所有基础格式的邮箱,再过滤掉多级顶级域名的情况:

awk '{
    while (match($0, /[A-Za-z0-9.]+@[A-Za-z0-9-]+\.[A-Za-z]{2,}/, mail_arr)) {
        candidate = mail_arr[0]
        # 排除末尾包含两个及以上顶级域名段的邮箱
        if (candidate !~ /\.[A-Za-z]+\.[A-Za-z]+$/) {
            print candidate
        }
        # 截断字符串,继续匹配后续内容
        $0 = substr($0, RSTART + RLENGTH)
    }
}' log.txt > mails.txt

解决方案3:纯POSIX扩展正则实现

也可以用扩展正则结合sed处理,避开PCRE特性:

grep -E -o '[A-Za-z0-9.]+@[A-Za-z0-9-]+\.[A-Za-z]{2,}([^A-Za-z.]|$)' log.txt | sed 's/[^A-Za-z0-9.@-]$//'
  • 正则部分匹配邮箱后接非字母点的字符或行尾
  • 用sed移除邮箱末尾可能附带的非邮箱字符(如空格、标点)

内容的提问来源于stack exchange,提问作者Y2theZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 00:57:01