正则表达式 - 匹配模式中的单词,但排除电子邮件地址内的单词

5
我希望找到与特定模式匹配的字符串中的单词。问题是,如果这些单词是电子邮件地址的一部分,则应该忽略它们。
简化起见,“正确单词”的模式为“\ w + \。\ w +” - 一个或多个字符,一个实际的句点和另一个系列的字符。
例如,导致问题的句子是“a.a b.b:c.c d.d@e.e.e”。
目标是仅匹配“[a.a,b.b,c.c]”。对于我构建的大多数Regexes,也会返回“e.e”(因为我使用某些单词边界匹配)。
例如:
re.findall(r"(?:^|\s|\W)(?
如何只在不包含“@”符号的单词中进行匹配?

不要试图编写一个聪明的正则表达式,也许先清理字符串会更好?首先去掉 \w+@\w+ 然后再处理。我经常使用 Python 进行 ETL 工作,通常清理垃圾数据然后拆分/处理数据会更容易、更快速。 - sniperd
http://www.rexegg.com/regex-best-trick.html#thetrick - bobble bubble
3个回答

2
我会先清理一下并简化正则表达式。
首先,我们有:
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]

1

正确地使用正则表达式解析电子邮件地址非常困难,但对于您简化的情况,只需简单定义单词为\w\.\w,电子邮件为包含@符号的任何序列,您可能会发现以下正则表达式可以满足您的需求:

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

这里的诀窍不在于关注下一个或前一个单词,而是关注当前捕获的单词应该像什么样子。
另一个诀窍是正确定义单词分隔符。在单词之前,我们允许多个空格、冒号和字符串开头,消耗这些字符但不捕获它们。在单词后面,我们几乎要求相同的内容(除了字符串结尾而不是开头),但我们不消耗这些字符-我们使用前瞻断言。

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演示

查看正则表达式演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接