python – pyparsing捕获具有给定标题的任意文本组作为嵌套列表

我有一个类似于的文本文件;

section header 1:
some words can be anything
more words could be anything at all
etc etc lala

some other header:
as before could be anything
hey isnt this fun

我试图用pyparser构造一个语法,当要求将解析后的结果作为列表时,这将导致以下列表结构; (IE;在遍历parsed.asList()元素时应该打印以下内容)

[‘section header 1:’,[[‘some words can be anything’],[‘more words could be anything at all’],[‘etc etc lala’]]]
[‘some other header:’,[[‘as before could be anything’],[‘hey isnt this fun’]]]

标题名称都是事先已知的,并且可能会出现或不出现各个标题.如果它们确实出现,则始终至少有一行内容.

我遇到的问题是,我无法解析解析器以识别’section header 1:’ands和’some other header:’的开始位置.我最终看到了一个parsed.asList();

[‘section header 1:’,[[”some words can be anything’],[‘more words could be anything at all’],[‘etc etc lala’],[‘some other header’],[”as before could be anything’],[‘hey isnt this fun’]]]

(IE:节标题1:正确看到,但是跟随它的每一个都被添加到节标题1,包括更多的标题行等.)

我尝试了各种各样的东西,以各种方式使用leaveWhitespace()和LineEnd(),但我无法弄清楚.

我正在讨厌的基本解析器是(人为的例子 – 实际上这是一个类定义等等.).

header_1_line=Literal('section header 1:')

text_line=Group(OneOrMore(Word(printables)))

header_1_block=Group(header_1_line+Group(OneOrMore(text_line)))

header_2_line=Literal('some other header:')

header_2_block=Group(header_2_line+Group(OneOrMore(text_line)))

overall_structure=ZeroOrMore(header_1_block|header_2_block)

正在被召唤

parsed=overall_structure.parseFile()

干杯,马特.

最佳答案
马特 –

欢迎来到pyparsing!你已陷入使用pyparsing最常见的陷阱之一,那就是人们比计算机更聪明.当您查看输入文本时,您可以轻松查看哪些文本可以是标题,哪些文本不可以.不幸的是,pyparsing不是那么直观,所以你必须明确告诉它什么可以和不可以是文本.

当您查看示例文本时,您不会接受任何文本行作为节标题中的可能文本.你怎么知道’其他标题:’作为文本无效?因为您知道该字符串与其中一个已知的标题字符串匹配.但是在您当前的代码中,您告诉pyparsing任何Word(printables)集合都是有效文本,即使该集合是有效的节头.

要解决此问题,您必须向解析器添加一些明确的前瞻. Pyparsing提供两种结构,NotAny和FollowedBy. NotAny可以使用’〜’运算符缩写,因此我们可以为文本编写这个伪代码表达式:

text = ~any_section_header + everything_up_to_the_end_of_the_line

这是一个使用负向前瞻的完整解析器,以确保您阅读每个部分,打破部分标题:

from pyparsing import ParserElement, LineEnd, Literal, restOfLine, ZeroOrMore, Group, StringEnd

test = """
section header 1:
 some words can be anything
 more words could be anything at all
 etc etc lala 

some other header:
 as before could be anything
 hey isnt this fun
"""
ParserElement.defaultWhitespaceChars=(" \t")
NL = LineEnd().suppress()
END = StringEnd()

header_1=Literal('section header 1:') 
header_2=Literal('some other header:')
any_header = (header_1 | header_2)
# text isn't just anything! don't accept header line, and stop at the end of the input string
text=Group(~any_header + ~END + restOfLine) 

overall_structure = ZeroOrMore(Group(any_header +
                                     Group(ZeroOrMore(text))))
overall_structure.ignore(NL)

from pprint import pprint
print(overall_structure.parseString(test).asList())

在我的第一次尝试中,我忘了也查找字符串的结尾,所以我的restOfLine表达式永远循环.通过为字符串结尾添加第二个前瞻,我的程序成功终止.为您留下的练习:不是枚举所有可能的标题,而是将标题行定义为以“:”结尾的任何行.

你的pyparsing努力祝你好运,
– 保罗

转载注明原文:python – pyparsing捕获具有给定标题的任意文本组作为嵌套列表 - 代码日志