【问题标题】:Regular Expression - Match Email Address with Exceptions正则表达式 - 将电子邮件地址与异常匹配
【发布时间】:2017-04-26 09:10:16
【问题描述】:

请仔细阅读问题,这不是关于验证电子邮件地址的问题!

我正在尝试构建一个正则表达式(目前在 C# 中),它从文本中提取所有电子邮件地址,但有两个特定的例外。

我明白了:

  • user1@company.com
  • user2@company.com
  • user3@company.com
  • user1@private.com
  • user2@private.com

所有在同一行的同一文本文件中,由空格字符分隔。

起初,我尝试匹配所有这些电子邮件地址,但以“user1”开头的电子邮件地址除外。我用过:

[\S]*(?<!user1)@[\S]*\..[a-zA-Z.]{1,}

效果很好。现在我有另一个要求:如果完整的电子邮件地址与“user2@private.com”匹配,也不匹配。所以它应该匹配“user2@company.com”,因此我不能使用:

[\S]*(?<!(user1|user2))@[\S]*\..[a-zA-Z.]{1,}

因此我尝试了一个额外的负面回顾:

([\S]*(?<!user1)@[\S]*\..[a-zA-Z.]{1,})(?<!user2@private\.com)

这不起作用,因为我猜它似乎对匹配“user2@private.co”感到满意。有什么办法可以实现我想要做的事情吗?我的头已经很痛了,...

我会使用额外的代码,但由于我使用的是第三方软件,它只给了我正则表达式的选项,而且只有一个正则表达式的选项,这就是我所拥有的,...

【问题讨论】:

  • 也许this approach 对你有用。用空格分割,获取匹配@"^\S+@\S+\.\S+$" 的项目并使用一些代码过滤掉不需要的匹配项。
  • 单个正则表达式解决方案 - (?&lt;!\S)(?!user1@|user2@private\.com(?!\S))\S+@\S+\.[a-zA-Z]{2,}(?!\S),但看起来不太好。
  • @WiktorStribiżew 非常好,...您想将其添加为答案吗?不过,我将需要一些时间来了解您所做的事情,...但我认为它有效。
  • @HimBromBeere:请再次阅读帖子,它与您发布的内容不重复。这与验证常规电子邮件地址无关。
  • 这不是关于验证电子邮件,而是关于提取类似电子邮件的子字符串,但有例外。

标签: c# regex pattern-matching


【解决方案1】:

看起来不太好的单个正则表达式解决方案是

(?<!\S)(?!user1@|user2@private\.com(?!\S))\S+@\S+\.[a-zA-Z]{2,}(?!\S)

请参阅regex demo

详情

  • (?&lt;!\S) - 前面没有非空白字符的位置
  • (?!user1@|user2@private\.com(?!\S)) - 该位置后面不能跟 user1@user2@private.com 后面不能跟非空白字符
  • \S+ - 1+ 非空格
  • @ - 文字 @
  • \S+ - 1+ 非空格
  • \. - 一个点
  • [a-zA-Z]{2,}(?!\S) - 2 个或更多 ASCII 字母后跟非空白字符。

一种更易读的方法是用空格分割,获取匹配@"^\S+@\S+\.\S+$"的项目,并使用一些代码过滤掉不需要的匹配项:

var s = @"Text user1@company.com here user2@company.com and user3@company.com here user1@private.com more user2@private.com";
var result = s.Split().Where(m => 
        Regex.IsMatch(m, @"^\S+@\S+\.\S+$") && m != "user2@private.com" && !m.StartsWith("user1@"));
foreach (var str in result)
    Console.WriteLine(str);
// => user2@company.com, user3@company.com

C# demo

【讨论】:

    【解决方案2】:

    您应该能够改为使用否定的前瞻性。如果您需要过滤掉明确的电子邮件,则以下解决方案应该可以工作。但请记住,它并不是完全可扩展的。您不希望在此处应用数千封电子邮件。

    ^(?!user1|user2(?!@company.com))[\S]*@[\S]*\..[a-zA-Z.]{1,}

    如果您怀疑这些规则中的许多规则可能会在将来应用,那么您可能需要考虑一种更好的方法。如果要过滤掉的电子邮件是明确的(不是模式),那么您可以在某处维护一个黑名单,并在提取/验证电子邮件地址模式后将它们过滤掉。

    【讨论】:

    • 您的正则表达式将匹配 'user1@company.com',但我需要它不匹配。它应该排除“user1@”,但只有“user2@private.com”,而不是“user2@company.com”...
    • @inzanez 感谢您的澄清。我更新了表达式以反映正则表达式需要忽略任何以user1 开头的地址和任何以user2 开头但仍匹配以user2@company.com 开头的地址的地址。让我知道这是否合适。
    • 我稍微改变了它,以便最终拆分工作: (?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    相关资源
    最近更新 更多