正则表达式查找 HTML 中未链接的原始电子邮件地址

Regex Find Raw E-mail Addresses that Hasn't Been Linked in HTML

我正在尝试创建一个正则表达式,用于从尚未在 HTML 中链接的长正文中查找原始电子邮件地址。例如,

我想用正确链接的电子邮件地址替换它们。

我试过:

html = html.replaceAll(
/(?:(?!href=['"]mailto:)(?!<a.*?>))([a-zA-Z0-9+._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)(?:(?!<\/a>))/gi, 
"<a href=\'mailto:\'></a>"
);

想法是找到电子邮件地址之前没有 href='mailto:<a> 标记,并且在 e 之后没有 </a> -邮件。但是,负前瞻 ?! 似乎没有给我预期的结果:

let regex = new RegExp(/(?:(?!href=['"]mailto:)(?!<a.*?>))([a-zA-Z0-9+._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)(?:(?!<\/a>))/, 'gi');
console.log(regex.test("href='mailto:name@example.com"))

正如您从上面的代码片段中看到的,尽管添加了负面前瞻,但针对正则表达式测试 href='mailto:name@example.com 是 returning true。

我也试过:

(.*)^(?:(?!href=['"]mailto:)(?!<a.*?>))([a-zA-Z0-9+._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)(?:(?!<\/a>))

它不匹配带有 href='mailto: 前缀的电子邮件,但现在

regex.test("1: name@example.com") // returns false

电子邮件地址可以内联,所以我不能在开头使用 ^ 运算符。

关于如何实现此目标的任何想法?提前致谢。

一种方法是使用以下模式的回调函数进行正则表达式替换:

<a href="mailto:\S+">.*?<\/a>|\S+@\S+\.\S+

这使用交替技巧来尝试首先找到其中已经包含电子邮件地址的锚标记。失败后,交替回退到在文本中的其他任何地方查找电子邮件地址。

var input = "Here is a tag with email <a href=\"mailto:name@example.com\">name@example.com</a> and here is just the email name@example.com";
console.log("INPUT: " + input);
var output = input.replace(/<a href="mailto:\S+">.*?<\/a>|\S+@\S+\.\S+/g, function(match, contents, offset, inp)
    {
        if (/<a href="mailto:\S+">.*?<\/a>/.test(match)) {
            return match;
        }
        else {
            return "<a href=\"mailto:" + match + "\">" + match + "<\/a>";
        }
    }
);
console.log("OUTPUT: " + output);

在上面的代码片段中,回调函数检查匹配项是否是已经具有电子邮件地址的锚标记,在这种情况下它只是 returns 相同的匹配项。对于所有其他电子邮件地址,它将它们包装在锚标记中,然后 returns 替换。