【问题标题】:How do I extract a list of email/mailbox strings within text or test if a string is a proper email address?如何提取文本中的电子邮件/邮箱字符串列表或测试字符串是否是正确的电子邮件地址?
【发布时间】:2013-03-21 15:19:20
【问题描述】:

给定一些任意文本,我想提取所有电子邮件地址和“邮箱说明符”(例如"Fred Smith" <fred@me.com>)。我查看了 NSDataDetector,但它不处理电子邮件地址。

【问题讨论】:

    标签: ios objective-c macos nsdatadetector


    【解决方案1】:

    解决这个问题的方法是获得一个非常好的算法,可以检测尽可能多的有效地址,并拒绝不正确的地址。最好的解决方案可能是使用 lex 和 yacc 构建的解析器,但使用正则表达式存在合理的解决方案。

    请参阅此site 以获取经过测试的正则表达式列表以及对问题和可能解决方案的更深入讨论。

    上述网站上显示的正则表达式针对 PHP 进行了格式化,并具有前导和尾随“/”标记,以及表示不区分大小写等的“标志”等(有关更多信息,请参阅此 site),所以这些在 Objective-C 项目中使用表达式之前需要剥离。此外,任何锚点也需要剥离,因为我们需要多个地址而不仅仅是一个(即“^”和“$”)。

    NSRegularExpression 是这里使用的类。我发现有用的是将正则表达式存储在我项目的文件中,这样您就不必担心转义所有反斜杠和引号。然后代码将表达式读入字符串,并按如下方式创建对象:

    NSString *fullPath = [[NSBundle mainBundle] pathForResource:self.regex ofType:@"txt"];
    NSString *pattern = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:NULL];
    __autoreleasing NSError *error = nil;
    reg = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; // some patterns may not need NSRegularExpressionCaseInsensitive
    assert(reg && !error);
    

    一旦你有了一个初始化的表达式,你就可以用它来返回一个范围列表,每个范围都是一个地址:

    NSArray *ret = [reg matchesInString:str options:0 range:NSMakeRange(0, [str length])];
    

    但是,我们知道所有电子邮件地址都包含一个“@”,因此在处理字符串之前验证该字符串是否至少包含一个可能是值得的。此外,由于文本中可能包含换行符和/或回车符,您可能需要先删除它们。最好将它们完全剥离,因为某些邮件程序可能会在地址的某个内部点拆分一行。

    一旦你有了地址范围的列表,那么大部分工作就完成了——如果你想要的只是地址的话。但是,地址通常以“邮箱说明符”格式显示,其中名称被添加到地址前,地址用“”包裹。这种格式在 RFC5322 的第 3.4 节中介绍。

    要从“邮箱说明符”中恢复名称,请检查地址是否用“”包裹,如果是,则查找“

    同样的技术可以用于实时验证——比如当文本字符串变成有效的电子邮件地址时启用提交按钮。在这种情况下,您评估每个用户更改的字符串,并启用/禁用提交按钮。

    如果所有这些看起来都需要大量的编码工作,您可以在 github 上获取一个开源项目。

    EDIT1:有关更快但不太严格的方法,请参阅 CodaFi 的评论。

    EDIT2:看起来“mailto: URL 的内容可能相当复杂,github 项目只处理最简单的,并没有对地址进行反编码。这将在以后的更新中解决。

    EDIT3:该项目已更新为完全处理“mailto:”对象,并返回到、cc、bcc、主题和正文,所有 URL 解码。

    【讨论】:

    • NSRegularExpressions 可能代价高昂。看看EtPanKit's LEPAddress class。它包括许多将地址数组转换为 RFC 标准化字符串的方法。
    • @CodaFi。有趣的项目,值得注意。但是,我在您提供的文件中看不到任何包含真正解析器的内容。当然,您可以查找包含在“”中的字符串,或者由空格分隔并包含“@”的字符串,但随后您会从随机文本样本中获取虚假地址。使用正则表达式技术虽然很慢,但实际上可以确保检测到的地址是真正有效的。在许多情况下,速度可能不是问题,但如果是,那么肯定需要替代更快的方法。
    • 这完全取决于它们的分隔方式。如果数组只是包含一些地址的垃圾,那你是对的,但是对于来自网络链接到电子邮件地址(激活消息组合)的字符串数组,这很棒。
    猜你喜欢
    • 1970-01-01
    • 2017-10-10
    • 2019-12-26
    • 1970-01-01
    • 2019-04-05
    • 2013-05-01
    • 2017-07-23
    • 2016-04-12
    • 2011-09-21
    相关资源
    最近更新 更多