Python 如何提取在文档中间的第1行到第3行?
如何使用pythonPython 如何提取在文档中间的第1行到第3行?,python,regex,Python,Regex,如何使用pythonre提取中间部分(第一行、第二行和第三行) --089e013d100acf582104f809fd8d Content-Type: text/plain; charset=UTF-8 first line second line third line --089e013d100acf582104f809fd8d 阅读邮箱的第一部分: #!/usr/bin/env python import poplib from email import parser pop_c
re
提取中间部分(第一行、第二行和第三行)
--089e013d100acf582104f809fd8d
Content-Type: text/plain; charset=UTF-8
first line
second line
third line
--089e013d100acf582104f809fd8d
阅读邮箱的第一部分:
#!/usr/bin/env python
import poplib
from email import parser
pop_conn = poplib.POP3_SSL('mail.company.com')
pop_conn.user('user')
pop_conn.pass_('')
#newest email has the highest message number
numMessages = len(pop_conn.list()[1])
(server_msg,body,octets) = pop_conn.retr(numMessages)
正则表达式实际上只是为简单(正则)模式设计的。理论上,正则表达式是表示有限状态机的一种方式。通常,它们用于标记化/lexer(将程序字符串拆分为一系列标记)或匹配常规字符串(例如罗马数字) 看起来您正在尝试解析多部分mime文档,例如:
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="mimetest"
This part is ignored.
--mimetest
Content-Type: text/plain
Part 1
--mimetest
Content-Type: text/rtf
\rtf{\par Part 2}
--mimetest--
这里有一个外部mime文档和两个内部mime文档。每个mime文档都有一个标题部分,由一个空行分隔,后跟内容
最好的方法是编写一个解析器,将头和内容一起读入字典。然后,您可以使用正则表达式定位边界并提取边界之间的文本,例如:
MIME_STATE_HEADER = 1
MIME_STATE_BODY = 2
def read_lines(text):
if isinstance(text, list):
return text
return re.split(r'\r?\n', text)
def parse_mime(text):
header_line = re.compile(r'^([A-Za-z\-]+): (.*)$')
state = MIME_STATE_HEADER
header = {}
body = []
for line in read_lines(text):
if state == MIME_STATE_HEADER:
if line == '':
state = MIME_STATE_BODY
continue
m = header_line.match(line)
if not m:
raise Exception('Invalid header section: %s' % line)
header[ m.group(1).lower() ] = m.group(2)
elif state == MIME_STATE_BODY:
body.append(line)
return header, body
def mime(text):
header, body = parse_mime(text)
content_type = re.compile(r'multipart/.*; boundary="(.*)"')
m = content_type.match(header['content-type'])
if m:
boundary = re.escape(m.group(1))
matcher = re.compile(r'\r?\n--%s(--)?\r?\n' % boundary)
parts = [ mime(part) for part in matcher.split('\n'.join(body))[1:-2] if part ]
return header, parts
return header, '\n'.join(body)
此代码将处理各种基于mime的文档,但有几个限制/错误:
Content-Type: multipart/related;
boundary="text"
内容类型:多部分/相关;边界=文本
开头)或HTTP/SMTP标识符/状态行这样的邮件存档
匹配行首^
匹配行尾$
匹配任何字符[abc]
,a
,b
(其中一个)c
匹配任何字符[a-z]
到a
z
转义字符\-
,因此它可以在-
表达式中使用[]
匹配表达式a+
a
匹配表达式的零个或多个实例a*
a
匹配任何字符
可选地匹配a?
(即匹配a
的零个或一个实例)a
与回车符匹配\r
捕获下一组中匹配的(a)
表达式的内容——通过a
m.group(n)
- 以上表达式中的任何其他内容都按原样匹配
^([A-Za-z\-]+):(.*)$
匹配MIME头中的头条目,使得m.group(1)
是头名称(例如“内容类型”),而m.group(2)
是该头的内容
\r?\n
匹配Windows或Linux样式的行终止符(MIME文档应该使用“\r\n”,但在本地保存文件时,可以将其转换为\n
)
multipart/*;boundary=“?(*)”?
在内容类型标题条目中查找用于边界的文本
\r?\n--%s(-)?\r?\n
定位单个边界(其中%s
是
动态添加)。注意:我已通过re.escape
传递边界字符串,以防止其被利用(即,如果它包含一个正则表达式,如boundary=“[a-z]”
)
实际上,您应该使用Python中支持解析RFC822(电子邮件/mime)文档的email
模块。for this声明:“对于简单的非MIME消息,此根对象的负载可能是包含消息文本的字符串。对于MIME消息,根对象将从其is_multipart()方法返回True,并且可以通过get_payload()和walk()方法访问子部分。”
更新:我创建了一个read_lines
帮助程序来支持字符串列表(例如poplib
)和字符串列表(例如f.read()
)
更新:用于在以下位置检测边界的--%s\r?\n(.*)\r?\n--%s
匹配器:
matcher = re.compile(r'--%s\r?\n(.*)\r?\n--%s' % (boundary, boundary))
parts = [ mime(part) for part in matcher.findall(body) ]
有两个问题:
re.compile(…,re.DOTALL)来解决)
[part0, None, part1, None, part2, ..., partN, '--', '']
其中,
part0
是第一个边界之前的部分。因此,[1:-2]
用于删除part0
和两个端点匹配,而如果是part
则用于避免无匹配。以下是我用来捕获三行的简单代码:
reobj = re.compile("Content-Type:.*?\n+([^\n]+)\n+([^\n]+)\n+([^\n]+)\n*")
match = reobj.search(subject)
if match:
line1 = match.group(1)
line2 = match.group(2)
line3 = match.group(3)
else:
result = ""
这是如何工作的?
我们将捕获一组捕获括号之间的每一行。它们将是组1、组2、组3
为了获得我们想要的内容,我们先匹配内容类型(不捕获它),然后再匹配所有内容,直到下一系列新行,然后再使用\n+
每一行都用([^\n]+)
捕获,这意味着“匹配任意数量的非新行字符”
捕获每一行后,我们将使用\n+
吃掉任意数量的新行。第3组之后的最后一行是可选的:\n*
(事实上,如果没有它,正则表达式可以工作。)
您的文档是否总是与此完全相同?并非如此。--089e013d100acf582104f809fd8d是定义不同内容类型块之间边界的边界线。非常感谢您的立即关注!没问题:p您需要定义一些规则。计算机如何找到这些行?它们总是第3行、第4行和第6行吗在边界之后?在这种情况下,我建议您不要使用正则表达式,而是以某种方式循环和计数。同意。如果这些行立即跟随Content-t