【问题标题】:Regex - Match words in pattern, except within email address正则表达式 - 匹配模式中的单词,电子邮件地址内除外
【发布时间】:2018-01-08 12:58:02
【问题描述】:

我正在寻找与特定模式匹配的字符串中的单词。 问题是,如果这些词是电子邮件地址的一部分,它们应该被忽略。

为简化起见,“专有词”\w+\.\w+ 的模式 - 一个或多个字符、一个实际句点和另一系列字符。

导致问题的句子,例如a.a b.b:c.c d.d@e.e.e

目标是仅匹配 [a.a, b.b, c.c] 。对于我构建的大多数正则表达式,e.e 也会返回(因为我使用了一些单词边界匹配)。

例如:

>>> re.findall(r"(?:^|\s|\W)(?<!@)(\w+\.\w+)(?!@)\b", "a.a b.b:c.c d.d@e.e.e") ['a.a', 'b.b', 'c.c', 'e.e']

如何只匹配不包含“@”的单词?

【问题讨论】:

  • 而不是试图让一个聪明的正则表达式运行,也许先清理字符串?首先剥离 \w+@\w+ 然后处理。我用 python 做了很多 ETL 工作,通常更容易/更快地清理垃圾,然后拆分/处理数据。

标签: python regex negative-lookahead negative-lookbehind


【解决方案1】:

您可以将类似电子邮件的子字符串与\S+@\S+\.\S+ 匹配,并在所有其他上下文中将您的模式与(\w+\.\w+) 匹配并捕获。使用re.findall 仅返回捕获的值并过滤掉空项(当有电子邮件匹配时,它们将在re.findall 结果中):

import re
rx = r"\S+@\S+\.\S+|(\w+\.\w+)"
s = "a.a b.b:c.c d.d@e.e.e"
res = filter(None, re.findall(rx, s))
print(res)
# => ['a.a', 'b.b', 'c.c']

请参阅Python demo

请参阅regex demo

【讨论】:

    【解决方案2】:

    使用正则表达式正确解析电子邮件地址非常困难,但对于您的简化情况,使用简单的单词定义 ~\w\.\w 和电子邮件 ~any sequence that contains @,您可能会发现这个正则表达式可以满足您的需求:

    >>> re.findall(r"(?:^|[:\s]+)(\w+\.\w+)(?=[:\s]+|$)", "a.a b.b:c.c d.d@e.e.e")
    ['a.a', 'b.b', 'c.c']
    

    这里的诀窍不是关注下一个或上一个单词的内容,而是关注当前捕获的单词的外观。

    另一个技巧是正确定义单词分隔符。 单词之前,我们将允许多个空格、: 和字符串开头,消耗这些字符,但不捕获它们。 我们需要几乎相同的单词之后(除了字符串结束,而不是开始),但我们不使用这些字符 - 我们使用前瞻断言。

    【讨论】:

      【解决方案3】:

      我肯定会先清理它并简化正则表达式。

      首先我们有

      words = re.split(r':|\s', "a.a b.b:c.c d.d@e.e.e")
      

      然后过滤掉其中包含@ 的单词。

      words = [re.search(r'^((?!@).)*$', word) for word in words]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-17
        • 1970-01-01
        • 2016-12-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-18
        相关资源
        最近更新 更多