Python 忽略与正则表达式不完全匹配的字符串?
我想使用正则表达式返回电子邮件的所有收件人。例如:Python 忽略与正则表达式不完全匹配的字符串?,python,regex,Python,Regex,我想使用正则表达式返回电子邮件的所有收件人。例如: Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST) From: donald.herrick@enron.com To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us, robertherrick@bankunited.com, kristi.demaiolo@enron.com, suresh.raghavan@enron.
Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST)
From: donald.herrick@enron.com
To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us,
robertherrick@bankunited.com, kristi.demaiolo@enron.com,
suresh.raghavan@enron.com, harry.arora@enron.com
Subject: FW: If Santa Answered his mail...
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-From: Donald W Herrick
X-To: brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com, Kristi Demaiolo, Suresh Raghavan, Harry Arora
X-cc:
X-bcc:
应返回(从“到:”行)brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us, robertherrick@bankunited.com,克里斯蒂。demaiolo@enron.com,苏雷什。raghavan@enron.com骚扰arora@enron.com
但是不是(从“X-To:”行)brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com
我当前的正则表达式是re.findall([To:\s][\w\.-]+@[\w\.-]+,text)
,它返回从“To:”、“X-To:”和“from:”行的所有内容
我的问题:
[To:\s]
部分不匹配李>
您误解了字符类的作用;您的模式匹配字符串中包含
T
、o
、:
或空白字符的任何位置
这是因为[To:\s]
为字符类建模,集合中的任何一个字符都将匹配。这就是为什么From:
行匹配;:
和d
之间的空格在这里就足够了
如果需要验证整个标题名,请使用^
将匹配锚定到行的开头,但删除该字符类:
r'^To:\s+[\w\.-]+@[\w\.-]+'
现在,如果使用re.MULTILINE
标志,则To:
部分仅在行首匹配:
>>> import re
>>> text = '''\
... Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST)
... From: donald.herrick@enron.com
... To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us,
... robertherrick@bankunited.com, kristi.demaiolo@enron.com,
... suresh.raghavan@enron.com, harry.arora@enron.com
... Subject: FW: If Santa Answered his mail...
... Mime-Version: 1.0
... Content-Type: text/plain; charset=us-ascii
... Content-Transfer-Encoding: 7bit
... X-From: Donald W Herrick
... X-To: brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com, Kristi Demaiolo, Suresh Raghavan, Harry Arora
... X-cc:
... X-bcc:
... '''
>>> re.findall(r'^To:\s+[\w\.-]+@[\w\.-]+', text)
[]
>>> re.findall(r'^To:\s+[\w\.-]+@[\w\.-]+', text, flags=re.M)
['To: brianherrick@email.msn.com']
这只能与第一个电子邮件地址匹配,并且只有当它不包含全名之类的内容时(例如,Brian Herrick
)
您必须匹配整个标题:
这会将匹配到:
标题,后跟任意数量的标题续行(以空格开头):
你必须从中提取电子邮件地址
就我个人而言,我会研究的,相反,这将使它更容易抓取标题:
import email
message = email.message_from_string(text)
to_headers = message.get_all('to')
addresses = email.utils.getaddresses(to_headers)
演示:
现在你有了所有的电子邮件地址
在使用正则表达式时也可以应用:
>>> email.utils.getaddresses(re.findall(r'^To:\s+((?:.*(?:\n[ \t]+)?)*)', text, flags=re.M))
[('', 'brianherrick@email.msn.com'), ('', 'herriceu2@tdprs.state.tx.us'), ('', 'robertherrick@bankunited.com'), ('', 'kristi.demaiolo@enron.com'), ('', 'suresh.raghavan@enron.com'), ('', 'harry.arora@enron.com')]
作为@MartijnPieters答案的补充,regex可能不是合适的工具
regex
模块:无限查找和其他功能
如果您想使用正则表达式,我建议您使用未完成而不是re
。此正则表达式将返回所有匹配项:
(?<=(?<!X\S+)To:\s*(?:[^@\s]+@[^\,\s]+,\s*)*?)[^@\s]+@[^\,\s]+
解释
- 我们有一个大的查找,然后是一个非常基本的电子邮件匹配器:
,它匹配任何不是arrobas或空格字符的字符,然后是arrobas,然后是任何不是逗号或空格字符的字符(输入中电子邮件分隔符的结尾)[^@\s]+@[^\,\s]+
- 如果需要,可以用更复杂的电子邮件正则表达式替换电子邮件匹配器
- 现在转到大的lookback```(?to:,只要它前面没有前面有
,正如负lookbackXsomething
(
- 非捕获组
根据需要匹配表达式(?:[^@\s]+[^\,\s]+,\s*)*?
中的[^@\s]+[^\,\s]+,\s*
量词),以允许后面的内容匹配。这是一个“电子邮件跳过器”,允许我们在每次匹配后逐渐跳过越来越多的电子邮件*?
只是一封简陋的电子邮件,后跟一个coma和可选的空白字符([^@\s]+@[^\,\s]+,\s*
不仅匹配空格,还匹配回车符、制表符等)\s
[To:\s]
不会做你认为它会做的事。'o:TT TTTo oT::'
也匹配,因为[…]
为一组字符建模,而不是序列。如果在字符集后有一个*
或+
,否则它只匹配一个字符。换句话说,当前表达式匹配T.-----。whoopee@foobar
仅仅因为它以T
、o
、:
或空格中的一个开头。Thanx。我会的查看电子邮件包,但我不知道这是否是我正在寻找的,因为我正在为txt文件(本例中碰巧包含电子邮件)构建一个通用解析器。我在表达式中有[to:\s]
的原因是,当我有to:\s
和多行标志时,它只返回第一个电子邮件地址(brianherrick@email.msn.com),其中,我需要将所有匹配项返回到[\w\.-]+@[\w\.-]+
,这些匹配项出现在“to:”之后,但不在“X-to:”之后。这可能吗?@user3797035:您只能匹配整个标题,而不能匹配单个电子邮件地址。@user3797035:添加了有关如何使用正则表达式提取所有收件人:
标题的详细信息,以及如何使用电子邮件.utils
包将这些标题解析为电子邮件地址的详细信息。您好,谢谢您的建议。您愿意成为能够解释正则表达式字符串的作用吗?特别是关于前向和后向断言?此表达式是否与re
不兼容?不,它不能与re
一起工作。支持此功能的仅有两个引擎是.NET和regex
模块(四大引擎中的两个,分别是PCRE和Perl)。对于Python中任何严重的正则表达式,您都需要该模块,该模块旨在替换re
。将添加解释。:)好的,添加了一个很长的解释,但如果有不清楚的地方或您需要更多详细信息,请告诉我。:)如果你有,比如说,一个X-Original-To:
标题,这将不起作用。你最好锚定到一行的开头;电子邮件标题确实跟随RFC是有原因的。:-@MartijnPieters谢谢你的想法,编辑了lookback来解释它。:)我没有考虑
>>> import email
>>> m = email.message_from_string(text)
>>> m.get_all('to')
['brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us, \n robertherrick@bankunited.com, kristi.demaiolo@enron.com, \n suresh.raghavan@enron.com, harry.arora@enron.com']
>>> email.utils.getaddresses(m.get_all('to'))
[('', 'brianherrick@email.msn.com'), ('', 'herriceu2@tdprs.state.tx.us'), ('', 'robertherrick@bankunited.com'), ('', 'kristi.demaiolo@enron.com'), ('', 'suresh.raghavan@enron.com'), ('', 'harry.arora@enron.com')]
>>> email.utils.getaddresses(re.findall(r'^To:\s+((?:.*(?:\n[ \t]+)?)*)', text, flags=re.M))
[('', 'brianherrick@email.msn.com'), ('', 'herriceu2@tdprs.state.tx.us'), ('', 'robertherrick@bankunited.com'), ('', 'kristi.demaiolo@enron.com'), ('', 'suresh.raghavan@enron.com'), ('', 'harry.arora@enron.com')]
>>> from email.parser import Parser
>>> headers = Parser().parsestr(email_str)
>>> pprint.pprint(map(str.strip, headers['to'].split()))
['brianherrick@email.msn.com,',
'herriceu2@tdprs.state.tx.us,',
'robertherrick@bankunited.com,',
'kristi.demaiolo@enron.com,',
'suresh.raghavan@enron.com,',
'harry.arora@enron.com']
(?<=(?<!X\S+)To:\s*(?:[^@\s]+@[^\,\s]+,\s*)*?)[^@\s]+@[^\,\s]+
import regex
subject = """Date: Wed, 6 Dec 2000 02:03:00 -0800 (PST)
From: donald.herrick@enron.com
To: brianherrick@email.msn.com, herriceu2@tdprs.state.tx.us,
robertherrick@bankunited.com, kristi.demaiolo@enron.com,
suresh.raghavan@enron.com, harry.arora@enron.com
Subject: FW: If Santa Answered his mail...
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-From: Donald W Herrick
X-To: brianherrick@email.msn.com, HERRICEU2@tdprs.state.tx.us, RobertHerrick@bankunited.com, Kristi Demaiolo, Suresh Raghavan, Harry Arora
X-cc:
X-bcc: """
pattern = "(?<=(?<!X\S+)To:\s*(?:[^@\s]+@[^\,\s]+,\s*)*?)[^@\s]+@[^\,\s]+"
for match in regex.finditer(pattern, subject):
print(match.group())
brianherrick@email.msn.com
herriceu2@tdprs.state.tx.us
robertherrick@bankunited.com
kristi.demaiolo@enron.com
suresh.raghavan@enron.com
harry.arora@enron.com