如何从任意文本中区分邮箱地址与MessageID,避免正则误匹配?
解决邮箱与Message-ID的正则匹配区分问题
你的问题核心是正则未通过上下文区分To:字段与Message-ID字段中的邮箱,导致两者都被匹配。之前尝试的(?<=To:\ )无效,是因为To:后的邮箱并非直接紧跟"To: ",而是隔着姓名和<符号。结合你启用的可变长度后向断言(experimental::vlb),可以用以下两种方案解决:
方案一:排除Message-ID中的邮箱
通过负向后向断言,阻止匹配Message-ID字段内的邮箱,同时限定邮箱位于<>标记内(符合测试文本格式):
my $re = qr{ (?<!Message-ID:\s*<) # 排除Message-ID开头<后的邮箱 ( (?: [\=a-z0-9!\#$%&'*+/?^_`{|}~-]+ (?:\.[\=a-z0-9!\#$%&'*+/?^_`{|}~-]+)* ) @ (?: (?!\d+\.\d+) (?=.{4,255}) (?: (?:[a-zA-Z0-9-]{1,63}(?<!-)\.)+ [a-zA-Z0-9-]{2,63} ) ) ) (?=>) # 确保邮箱以>结尾 }xims;
方案二:仅匹配To:行内的邮箱
通过正向后向断言,限定邮箱必须出现在To:行的<标记之后:
my $re = qr{ (?<=To:.*<) # 匹配To:行中<后的内容 ( (?: [\=a-z0-9!\#$%&'*+/?^_`{|}~-]+ (?:\.[\=a-z0-9!\#$%&'*+/?^_`{|}~-]+)* ) @ (?: (?!\d+\.\d+) (?=.{4,255}) (?: (?:[a-zA-Z0-9-]{1,63}(?<!-)\.)+ [a-zA-Z0-9-]{2,63} ) ) ) (?=>) }xims;
两种方案运行后都会得到你期望的输出:
tbruner@foo.com foo@bar.com
如果实际场景需要匹配Cc:、Bcc:等其他字段的邮箱,可扩展断言逻辑,比如将To:替换为(To:Cc:Bcc:)。
内容的提问来源于stack exchange,提问作者Todd
相关产品推荐
相关产品推荐

