我需要帮助来了解正则表达式中的排除项。
我从Jupyter笔记本开始:
import re
file = open('names.txt', encoding='utf-8')
data = file.read()
file.close()
然后我无法执行排除规则。读取的文件中包含12个电子邮件字符串,其中3个包含“ .gov”。
有人告诉我,这只会返回不是.gov的那些文件:
re.findall(r'''
[-+.\w\d]*\b@[-+\w\d]*.[^gov]
''', data, re.X|re.I)
不是。它返回所有电子邮件,并在“ @”之后的“ gov”中排除任何字符;例如:
abc123@abc.c # 'o' is in 'gov' so it ends the returned string there
456@email.edu
governmentemail@governmentaddress. #'.gov' omitted
我尝试使用?!我在网上发现各种各样的形式都无济于事。
例如,有人告诉我以下语法将排除整个匹配项,而不仅仅是那些字符:
#re.findall(r'''
# ^/(?!**SPECIFIC STRING TO IGNORE**)(**DEFINITION OF STRING TO RETURN**)$
#''', data, re.X|re.I)
但是以下内容仅返回一个空列表:
#re.findall(r'''
# ^/(?!\b[-+.\w\d]*@[-+.\w\d]*.gov)([-+.\w\d]*@[-+.\w\d].[\w]*[^\t\n])$
#''', data, re.X|re.I)
我尝试使用此问题的建议:
Regular expression to match a line that doesn't contain a word
re.findall(r'''
[-+.\w\d]*\b@[-+\w\d]*./^((?!.gov).)*$/s # based on syntax /^((?!**SUBSTRING**).)*$/s
#^ this slash is where different code starts
''', data, re.X|re.I)
这应该是内联语法,我认为通过包含斜杠,我可能会犯一个错误:
re.findall(r'''
[-+.\w\d]*\b@[-+\w\d]*./(?s)^((?!.gov).)*$/ # based on syntax /(?s)^((?!**SUBTRING**).)*$/
''', data, re.X|re.I)
这将返回一个空列表:
re.findall(r'''
[-+.\w\d]*\b@[-+\w\d]*.(?s)^((?!.gov).)*$ # based on syntax (?s)^((?!**SUBTRING**).)*$
''', data, re.X|re.I)
请帮助我了解如何使用?!或^或其他排除语法,以返回不包含另一个指定字符串的指定字符串。
谢谢!
答案 0 :(得分:1)
关于您尝试过的模式的一些注释
模式[-+.\w\d]*\b@
的这一部分可以缩短为[-+.\w]*\b@
,因为\w
也与\d
匹配,请注意,它也将不与点匹配。
使用[-+.\w\d]*\b@
可以防止破折号在@
之前匹配,但可以匹配---a@.a
字符类[-+.\w\d]*
被重复0+次,但是它永远不能匹配0+次,因为单词边界\b
在空白或行首与{{ 1}}
请注意,不转义点@
会匹配除换行符以外的任何字符
.
是一个tempered greedy token,它将从字符串的开头匹配任何字符,除了换行符,断言右边的字符除换行符后跟{{ 1}},直到字符串结尾一种选择可能是使用经过调节的贪婪令牌来断言^((?!.gov).)*$
之后不存在gov
。
@
有关各个部分的说明
.gov
匹配1次以上列出的任何游戏[-+.\w]+\b@(?:(?!\.gov)\S)+(?!\S)
单词边界和匹配[-+.\w]+
\b@
非捕获组
@
负向前进,断言右边的不是
(?:
匹配(?!
\.gov
提前关闭.gov
匹配非空格字符)
关闭非捕获组并重复1次以上\S
负向查找,断言右边的内容是非空格字符,以防止部分匹配您可以通过不匹配)+
或空白字符,然后匹配(?!\S)
然后再匹配不存在字符串@
的非空白字符来使模式更宽: / p>
@
答案 1 :(得分:1)
首先,您用于识别电子邮件地址的正则表达式看起来不太正确。例如,它将接受@13a
为有效。有关一些简化,请参见How to check for valid email address?。我将使用:[^@]+@[^@]+\.[^@]+
,同时建议您也排除空格字符,因此,在您的特定情况下:
^([^@\s]+@[^@\s]+\.[^@\s.]+)
我还向最后一个字符类.
添加了[^@\s.]+
,以确保它表示顶级域。但是我们不希望电子邮件地址以.gov
结尾。我们的正则表达式会在最后指定匹配顶级域名的地方:
\.
匹配句号。[^@\s.]+
匹配一个或多个非空格,非句点字符。在上面的步骤2中,我们应该首先应用负向超前,即确保下一个字符不是gov
的条件。但是要确保我们不进行部分匹配(如果顶级域为government
,那可以),gov
后必须跟空格或行尾取消资格。所以我们有:
^([^@\s]+@[^@\s]+\.(?!gov(?:\s|$))[^@\s.]+)
import re
text = """abc123@abc.c # 'o' is in 'gov' so it ends the returned string there
456@email.edu
governmentemail@governmentaddress. #'.gov' omitted
test@test.gov
test.test@test.org.gov.test
"""
print(re.findall(r'^([^@\s]+@[^@\s]+\.(?!gov(?:\s|$))[^@\s.]+)', text, flags=re.M|re.I))
打印:
['abc123@abc.c', '456@email.edu', 'test.test@test.org.gov.test']
因此,在我对问题test.test@test.org.gov.test
的理解中,因为gov
是 not 的顶级域。 governmentemail@governmentaddress.
被拒绝是因为它不是有效的电子邮件地址。
如果您不希望在域的任何级别使用gov
,请使用此正则表达式:
^([^@\s]+@(?!(?:\S*\.)?gov(?:\s|\.|$))[^@\s]+\.[^@\s]+)
在看到@
符号之后,这可以确保后面的内容不是一个可选的句点,后面跟着gov
,后面是另一个句点,空格字符或行尾。
import re
text = """abc123@abc.c # 'o' is in 'gov' so it ends the returned string there
456@email.edu
governmentemail@governmentaddress. #'.gov' omitted
test@test.gov
test.test@test.org.gov.test
"""
print(re.findall(r'^([^@\s]+@(?!(?:\S*\.)?gov(?:\s|\.|$))[^@\s]+\.[^@\s]+)', text, flags=re.M|re.I))
打印:
['abc123@abc.c', '456@email.edu']