解析 pyparsing 组混合字符词
Parsing pyparsing group of mixed character words
我正在尝试使用 pyparsing 解析来自维基百科信息框的数据字段。首先,以下代码有效:
from pyparsing import *
test_line = """{{Infobox company | name = Exxon Mobil Corp | num_employees_year = 2015 }}"""
data_group = Group(
Suppress("|") +
OneOrMore(White()).suppress() +
Word(alphanums + printables)("key") +
OneOrMore(White()).suppress() +
Suppress("=") +
OneOrMore(White()).suppress() +
OneOrMore(Word(alphanums))("value") +
ZeroOrMore(White()).suppress()
)
infobox_parser = (
Literal("{{").suppress() +
Word("Infobox") +
White().suppress() +
Word("company") +
OneOrMore(White()).suppress() +
OneOrMore(data_group)("values") +
Literal("}}").suppress()
)
print(infobox_parser.parseString(test_line))
产生结果:
['Infobox', 'company', ['name', 'Exxon', 'Mobil', 'Corp'], ['num_employees_year', '2015']]
问题是当我将测试字符串更改为
test_line = """{{Infobox company | name = Exxon Mobil Corp. | num_employees_year = 2015 }}"""
它失败了,因为我引入了“.”。作为 'Corp.' 的一部分。我想我可以通过将 Group 对象更改为
来解决这个问题
data_group = Group(
Suppress("|") +
OneOrMore(White()).suppress() +
Word(alphanums + printables)("key") +
OneOrMore(White()).suppress() +
Suppress("=") +
OneOrMore(White()).suppress() +
OneOrMore(Word(alphanums + printables))("value") +
ZeroOrMore(White()).suppress()
)
但我收到以下错误:
pyparsing.ParseException: Expected "}}" (at char 91), (line:1, col:92)
我在这里错过了什么?提前致谢。
只是几件事。最重要的是,pyparsing 不像正则表达式那样进行回溯。也就是说,这样的事情是行不通的:
data = '{' + OneOrMore(Word(printables))("data") + '}'
print(data.parseString('{ this is some data }'))
为什么?因为终止 '}' 也 匹配为 Word(printables)
,所以 OneOrMore
将一直持续到最后,然后失败,因为没有终止 ' }' 读取数据后才能找到。
直到最近,解决方案是在 OneOrMore
表达式中包含一个警卫,一个负面的 lookahed 说法实际上 "I want Word(printables), but first check if it's a '}' - I don't want that",看起来像这样:
data = '{' + OneOrMore(~Literal('}') + Word(printables))("data") + '}'
但这太常见了,我最近在 ZeroOrMore
和 OneOrMore
:
中添加了一个可选的 stopOn
参数
data = '{' + OneOrMore(Word(printables), stopOn=Literal('}'))("data") + '}'
在你的例子中,每个 data_group 解析一个 key=value
对,当你只解析 OneOrMore(Word(alphanums))
时你的值很好。但是一旦你将其更改为 OneOrMore(Word(alphanums+printables))
,你的重复项将贪婪地匹配下一个 '|'或终止 '}}',并像上面的示例一样失败。
其他几项:
pyparsing 将为您跳过空格。所有这些 White() 元素都是完全不必要的。
在一些地方您使用 Word 不正确,例如 Word("Infobox")
。在您的有限示例中,这可以匹配,但请记住,Word 是用您要匹配的字符集定义为单词组的,因此 Word("Infobox")
不仅会匹配 "Infobox",还会匹配任何由字母 'I'、'n'、'f'、'o'、'b'、and/or、'x' 组成的其他单词,例如"Inbox"、"IbIx"、"xoxoxox" 等。在这种情况下,您想要的 pyparsing class 将是 Literal
或 Keyword
.
退一步看,您的 data_group 似乎是 key=value
对,带有分隔符“|”。我建议为此使用 delimitedList
。
最后,使用dump()
输出解析后的数据,这将有助于可视化结构和结果名称。
进行这些更改后,您的代码如下所示:
data_group = Group(
Word(alphas, alphanums+'_')("key") +
Suppress("=") +
originalTextFor(OneOrMore(Word(printables), stopOn=Literal('|') | '}}'))("value")
)
infobox_parser = (
Literal("{{").suppress() +
Keyword("Infobox") +
Keyword("company") + '|' +
Group(delimitedList(data_group, '|'))("values") +
Literal("}}").suppress()
)
print(infobox_parser.parseString(test_line).dump())
给予:
['Infobox', 'company', '|', [['name', 'Exxon Mobil Corp.'], ['num_employees_year', '2015']]]
- values: [['name', 'Exxon Mobil Corp.'], ['num_employees_year', '2015']]
[0]:
['name', 'Exxon Mobil Corp.']
- key: name
- value: Exxon Mobil Corp.
[1]:
['num_employees_year', '2015']
- key: num_employees_year
- value: 2015
我正在尝试使用 pyparsing 解析来自维基百科信息框的数据字段。首先,以下代码有效:
from pyparsing import *
test_line = """{{Infobox company | name = Exxon Mobil Corp | num_employees_year = 2015 }}"""
data_group = Group(
Suppress("|") +
OneOrMore(White()).suppress() +
Word(alphanums + printables)("key") +
OneOrMore(White()).suppress() +
Suppress("=") +
OneOrMore(White()).suppress() +
OneOrMore(Word(alphanums))("value") +
ZeroOrMore(White()).suppress()
)
infobox_parser = (
Literal("{{").suppress() +
Word("Infobox") +
White().suppress() +
Word("company") +
OneOrMore(White()).suppress() +
OneOrMore(data_group)("values") +
Literal("}}").suppress()
)
print(infobox_parser.parseString(test_line))
产生结果:
['Infobox', 'company', ['name', 'Exxon', 'Mobil', 'Corp'], ['num_employees_year', '2015']]
问题是当我将测试字符串更改为
test_line = """{{Infobox company | name = Exxon Mobil Corp. | num_employees_year = 2015 }}"""
它失败了,因为我引入了“.”。作为 'Corp.' 的一部分。我想我可以通过将 Group 对象更改为
来解决这个问题data_group = Group(
Suppress("|") +
OneOrMore(White()).suppress() +
Word(alphanums + printables)("key") +
OneOrMore(White()).suppress() +
Suppress("=") +
OneOrMore(White()).suppress() +
OneOrMore(Word(alphanums + printables))("value") +
ZeroOrMore(White()).suppress()
)
但我收到以下错误:
pyparsing.ParseException: Expected "}}" (at char 91), (line:1, col:92)
我在这里错过了什么?提前致谢。
只是几件事。最重要的是,pyparsing 不像正则表达式那样进行回溯。也就是说,这样的事情是行不通的:
data = '{' + OneOrMore(Word(printables))("data") + '}'
print(data.parseString('{ this is some data }'))
为什么?因为终止 '}' 也 匹配为 Word(printables)
,所以 OneOrMore
将一直持续到最后,然后失败,因为没有终止 ' }' 读取数据后才能找到。
直到最近,解决方案是在 OneOrMore
表达式中包含一个警卫,一个负面的 lookahed 说法实际上 "I want Word(printables), but first check if it's a '}' - I don't want that",看起来像这样:
data = '{' + OneOrMore(~Literal('}') + Word(printables))("data") + '}'
但这太常见了,我最近在 ZeroOrMore
和 OneOrMore
:
stopOn
参数
data = '{' + OneOrMore(Word(printables), stopOn=Literal('}'))("data") + '}'
在你的例子中,每个 data_group 解析一个 key=value
对,当你只解析 OneOrMore(Word(alphanums))
时你的值很好。但是一旦你将其更改为 OneOrMore(Word(alphanums+printables))
,你的重复项将贪婪地匹配下一个 '|'或终止 '}}',并像上面的示例一样失败。
其他几项:
pyparsing 将为您跳过空格。所有这些 White() 元素都是完全不必要的。
在一些地方您使用 Word 不正确,例如
Word("Infobox")
。在您的有限示例中,这可以匹配,但请记住,Word 是用您要匹配的字符集定义为单词组的,因此Word("Infobox")
不仅会匹配 "Infobox",还会匹配任何由字母 'I'、'n'、'f'、'o'、'b'、and/or、'x' 组成的其他单词,例如"Inbox"、"IbIx"、"xoxoxox" 等。在这种情况下,您想要的 pyparsing class 将是Literal
或Keyword
.退一步看,您的 data_group 似乎是
key=value
对,带有分隔符“|”。我建议为此使用delimitedList
。最后,使用
dump()
输出解析后的数据,这将有助于可视化结构和结果名称。
进行这些更改后,您的代码如下所示:
data_group = Group(
Word(alphas, alphanums+'_')("key") +
Suppress("=") +
originalTextFor(OneOrMore(Word(printables), stopOn=Literal('|') | '}}'))("value")
)
infobox_parser = (
Literal("{{").suppress() +
Keyword("Infobox") +
Keyword("company") + '|' +
Group(delimitedList(data_group, '|'))("values") +
Literal("}}").suppress()
)
print(infobox_parser.parseString(test_line).dump())
给予:
['Infobox', 'company', '|', [['name', 'Exxon Mobil Corp.'], ['num_employees_year', '2015']]]
- values: [['name', 'Exxon Mobil Corp.'], ['num_employees_year', '2015']]
[0]:
['name', 'Exxon Mobil Corp.']
- key: name
- value: Exxon Mobil Corp.
[1]:
['num_employees_year', '2015']
- key: num_employees_year
- value: 2015