我有一个类似于的文本文件;
节标题1:
有些单词可以是任何
更多单词可以是任何东西
等等lala其他一些标题:
像以前一样可能是任何
嘿,这不是很有趣
我正在尝试用pyparser构造一个语法,当要求将解析结果作为列表时,这将导致以下列表结构; (IE;在遍历parsed.asList()元素时应该打印以下内容)
['节目标题1:',[['某些单词可以是任何内容'],['更多单词可以是任何内容'],['etc etc lala']]]
['其他标题:',[[ '就像之前可能是任何事情',['嘿,这不是很有趣']]]
标题名称都是事先已知的,并且可能会出现或不出现各个标题.如果它们确实出现,则始终至少有一行内容.
我遇到的问题是,我无法解析解析器以识别'section header 1:'ands和'some other header:'的开始位置.我最终看到了一个parsed.asList();
['节目标题1:',[[''某些单词可以是任何'],['更多单词可以是任何东西'],['etc etc lala'],['其他标题'],[' '就像之前可能是任何事情',['嘿,这不是很有趣']]]
(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)
Run Code Online (Sandbox Code Playgroud)
正在被召唤
parsed=overall_structure.parseFile()
Run Code Online (Sandbox Code Playgroud)
干杯,马特.
Pau*_*McG 13
马特 -
欢迎来到pyparsing!你已经陷入了与pyparsing合作最常见的陷阱之一,那就是人们比计算机更聪明.当您查看输入文本时,您可以轻松查看哪些文本可以是标题,哪些文本不可以.不幸的是,pyparsing不是那么直观,所以你必须明确告诉它什么可以和不可以是文本.
当您查看示例文本时,您不会接受任何文本行作为节标题中的可能文本.你怎么知道"其他一些标题:"作为文本无效?因为您知道该字符串与其中一个已知的标题字符串匹配.但是在您当前的代码中,您已告知pyparsing任何集合Word(printables)都是有效文本,即使该集合是有效的节头.
要解决此问题,您必须向解析器添加一些明确的前瞻.Pyparsing提供两种结构,NotAny和FollowedBy.NotAny可以使用'〜'运算符缩写,因此我们可以为文本编写这个伪代码表达式:
text = ~any_section_header + everything_up_to_the_end_of_the_line
Run Code Online (Sandbox Code Playgroud)
这是一个使用负向前瞻的完整解析器,以确保您阅读每个部分,打破部分标题:
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())
Run Code Online (Sandbox Code Playgroud)
在我的第一次尝试中,我忘了也寻找字符串的结尾,所以我的restOfLine表达式永远循环.通过为字符串结尾添加第二个前瞻,我的程序成功终止.为您留下的练习:不是枚举所有可能的标题,而是将标题行定义为以":"结尾的任何行.
祝你的pyparsing努力好运, - 保罗