相关于:Python parsing bracketed blocks
我有一个具有以下格式的文件:
#
here
are
some
strings
#
and
some
others
#
with
different
levels
#
of
#
indentation
#
#
#
因此,一个块由开始的
#
和结尾的#
定义。但是,第n-1个块的结尾#
也是第n个块的起始#
。我正在尝试编写一个函数,给定这种格式,它将检索每个块的内容,并且这也可能是递归的。
首先,我从正则表达式开始,但是我很快放弃了(我想你猜对了),所以我尝试使用
pyparsing
,但是我不能简单地写print(nestedExpr('#','#').parseString(my_string).asList())
因为它引发
ValueError
异常(ValueError: opening and closing strings cannot be the same
)。知道我无法更改输入格式后,我有没有比
pyparsing
更好的选择了?我也尝试使用以下答案:https://stackoverflow.com/a/1652856/740316,并用
{
替换了}
/ #/#
,但它无法解析字符串。 最佳答案
不幸的是(对您而言),您的分组不仅取决于分隔的“#”字符,而且还取决于缩进级别(否则,['with','different','levels']
将与先前的组['and','some','others']
处于同一级别)。解析缩进敏感的语法并不是pyparsing的强项-可以做到,但是并不令人满意。为此,我们将使用pyparsing帮助程序宏indentedBlock
,该宏还要求我们定义一个列表变量,indentedBlock
可以将其用于缩进堆栈。
请参阅下面代码中的嵌入式注释,以了解如何对pyparsing和indentedBlock
使用一种方法:
from pyparsing import *
test = """\
#
here
are
some
strings
#
and
some
others
#
with
different
levels
#
of
#
indentation
#
#
#"""
# newlines are significant for line separators, so redefine
# the default whitespace characters for whitespace skipping
ParserElement.setDefaultWhitespaceChars(' ')
NL = LineEnd().suppress()
HASH = '#'
HASH_SEP = Suppress(HASH + Optional(NL))
# a normal line contains a single word
word_line = Word(alphas) + NL
indent_stack = [1]
# word_block is recursive, since word_blocks can contain word_blocks
word_block = Forward()
word_group = Group(OneOrMore(word_line | ungroup(indentedBlock(word_block, indent_stack))) )
# now define a word_block, as a '#'-delimited list of word_groups, with
# leading and trailing '#' characters
word_block <<= (HASH_SEP +
delimitedList(word_group, delim=HASH_SEP) +
HASH_SEP)
# the overall expression is one large word_block
parser = word_block
# parse the test string
parser.parseString(test).pprint()
印刷品:
[['here', 'are', 'some', 'strings'],
['and',
'some',
'others',
[['with', 'different', 'levels'], ['of', [['indentation']]]]]]
关于python - pyparsing,开始和结束字符串相同,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29522805/