Bash正则表达式匹配电子邮件

4
我正在尝试在Bash中使用正则表达式匹配一些电子邮件地址。 目前已经得到了以下表达式:
"^[a-zA-Z0-9!#\$%&'\*\+/=?^_\`{|}~-]+(\.[a-zA-Z0-9!#\$%&'\*\+/=?^_\`{|}~-]+)*@([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\$"

这段代码可以成功匹配我需要的所有电子邮件,但是当我尝试添加"To: "字段时,似乎无法得到任何匹配项,我不确定为什么。

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

我知道的是这应该与"To: bob@bob.co.uk"相匹配,但实际上并没有匹配成功:( 有什么建议吗?
代码示例
Reply-To: "service@paypal.com" <service@paypal.com>
To: bob@bob.co.uk
Date: Mon, 21 Jun 2012 21:34:10 -0300

用于搜索文件并添加到数组中的代码

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


for i in $(cat mailbox.mbx); do 
    if [[ $i =~ $regex ]]; then
    echo $i
    sortarray[$index]=$i
    index=$(($index+1))
    fi
done

所以您的字符串是否包含[email]标签?电子邮件地址以空格结尾吗?请发布完整字符串。 - VladL
不好意思,它并没有那样,那是从复制粘贴中自动输入的。现在它已经完全正确了。 - user1298620
请返回包含电子邮件的完整字符串。 - VladL
它正在从一个大文件中解析,但是上面的示例已经显示出来了。 例如:“To: bob@bob.co.uk” 单独一行。第一个正则表达式可以很好地捕获它,而第二个则没有捕获任何内容。 - user1298620
需要更多信息,电子邮件是如何开始和结束的?是否带有标签、空格、行首或行尾等? - VladL
显示剩余3条评论
2个回答

3

bash正则表达式不支持Perl的\s。你需要使用POSIX的[[:space:]]。另外,你应该在那里添加一个量词。

我看到你在$regex中有锚点:这些是否让你感到困扰?

对于像这样庞大的正则表达式,我喜欢一步一步地构建它们:

char='[[:alnum:]!#\$%&'\''\*\+/=?^_\`{|}~-]'
name_part="${char}+(\.${char}+)*"
domain="([[:alnum:]]([[:alnum:]-]*[[:alnum:]])?\.)+[[:alnum:]]([[:alnum:]-]*[[:alnum:]])?"
begin='(^|[[:space:]])'
end='($|[[:space:]])'

# include capturing parentheses, 
# these are the ** 2nd ** set of parentheses (there's a pair in $begin)
re_email="${begin}(${name_part}@${domain})${end}"

line="To: joe.smith@example.com"

[[ $line =~ $re_email ]] && echo ${BASH_REMATCH[2]}
# prints: joe.smith@example.com

当然,电子邮件地址非常复杂--请参考http://www.w3.org/Protocols/rfc822/#z8,并且注释和空格几乎可以出现在任何地方。事实上,(hi there) "我的名字".lastname (another comment) @ domain.(really)invalid应该被认为是有效的地址。有一个Perl模块Email::Address可以生成这个正则表达式:
$ perl -MEmail::Address -E 'say $Email::Address::addr_spec'  
(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\\,."\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\\,."\s]+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*"(?-xism:(?-xism:[^\\"])|(?-xism:\\(?-xism:[^\x0A\x0D])))+"(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*))\@(?-xism:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\\,."\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\\,."\s]+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*\[(?:\s*(?-xism:(?-xism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D]))))*\s*\](?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|))*\s*\)\s*)))*\s*\)\s*)|\s+)*)))

这是一个非常好的解释,非常有启发性,真正有帮助,特别是通过变量拆分正则表达式并重新构建。 - user1298620

1

这个正则表达式应该匹配所需的字符串:

"^To: (.+@.+)$"

该电子邮件存储在$1中。


很抱歉,没有"To: ",它与电子邮件不匹配,但有了它就找不到匹配项。它还需要实现原始的正则表达式(或尽可能接近,但一旦找到初始的To:,我可以修复它)。已将我的代码添加到主题中。 - user1298620
@DanFarrall 如果是 Reply-To: 的情况,电子邮件的开头和结尾都有 **"**,但如果是 To: 的情况就没有。你确定这样正确吗? - VladL
@DanFarrall,你缺少像标签、特殊符号等的东西。将第一个输出重定向到文本文件,并使用不同的文本查看器/编辑器查看它。 - VladL
我尝试过使用仅包含"To: bob@bob.co.uk"的纯文本文件,但是To:无法匹配。您是否测试过您的解决方案并发现它有效?我在运行OS X,但在这种情况下它不应该有任何影响,对吗? - user1298620
@DanFarrall 我已在C#中测试过它,但这不应有任何影响,因为我没有使用Perl或常见的正则表达式特定元素。 - VladL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接