无法编译循环中的所有模式

时间:2018-08-03 20:33:03

标签: python regex python-3.x

我已经用python与re模块结合编写了一个脚本,以从少量文本中抓取一些内容。如果我单独尝试,我定义的模式可以成功找到并获取它们。

但是,我的问题是如何在循环中使用这些模式一次性拍摄它们?最重要的是,并非所有文本块中的所有字段都可用。

我尝试过(以下所有模式都是有效的):

import re

content="""
Name: Larry King
Telephone: 514 353-4119 
Website: http://www.lexor.biz 

Name: Allen Smith
Telephone: 819 986-3429 
Website: http://aefournier.com 
Email: aefournier@videotron.ca 

Name: Paul adams
Telephone: 1-819-477-6656 
Email: info@lexor.biz 
"""
pattern = re.compile(r"Name:\s+(.*)")
# pattern = re.compile(r"Telephone:\s+(.*)")
# pattern = re.compile(r"Email:\s+(.*)")
# pattern = re.compile(r"Website:\s+(.*)")
for item in pattern.finditer(content):
    print(item.group(1))

我期望第一个容器具有输出(电子邮件在第一个块中丢失,因此空白字段应该用N/A填充):

Larry King 514 353-4119 http://www.lexor.biz N/A

and so on--

1 个答案:

答案 0 :(得分:2)

如果您输入的内容始终是相同的顺序(名称,电话,网站,电子邮件),但后面的一些可选内容是可选的,那么您可以使用正则表达式进行输入。但这可能不是一个好主意。

我们可以将这四个模式连接起来,并在它们之间使用适当的空格模式(我使用\n,该模式适用于您发布的示例,但我不确定它是否正确),并标记后三个可选项,方法是将它们放在一个非捕获组中并附加一个?

Name:\s+(.*)\n(?:Telephone:\s+(.*)\n)?(?:Website:\s+(.*)\n)?(?:Email:\s+(.*)\n)?

您可以in action at regex101看到它。

请注意,例如,最后一场比赛没有第3组,只有第1、2和4组。

(给这些组?P<names>可能会更好一些,因此您可以通过名称来引用它们。)


但是,通过将其视为由空白行分隔的块序列(每个块均采用Header:Value格式)来解决,则要容易得多。您甚至不需要正则表达式;只是遍历了可迭代的字符串。

或者,更简单地说,使用itertools.groupby为您将其分成多个块。非空行是真实的,空行是虚假的,所以只需按真实性分组:

lines = content.splitlines()

for nonempty, group in itertools.groupby(lines, bool):
    if nonempty:
        print('New Entry')
        for line in group:
           header, value = line.split(':', 1)
           print(header.strip(), value.strip())

或者,假设您想将这些条目实际收集到某种结构中,例如按名称键入的dict的dict:

def parse(lines):
    for nonempty, group in itertools.groupby(lines, bool):
        if nonempty:
            pairs = (line.split(':', 1) for line in group)
            yield {header.strip(): value.strip() for header, value in pairs}

entries = {entry['Name']: entry for entry in parse(content.splitlines())}