pyparsing 开始和结束字符串相同
pyparsing with starting and ending string being the same
相关: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
更好的选择吗?
我也尝试使用这个答案:,并将 {
/}
替换为 #/#
但它无法解析字符串。
不幸的是(对您而言),您的分组不仅取决于分隔的“#”字符,还取决于缩进级别(否则,['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 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
更好的选择吗?
我也尝试使用这个答案:,并将 {
/}
替换为 #/#
但它无法解析字符串。
不幸的是(对您而言),您的分组不仅取决于分隔的“#”字符,还取决于缩进级别(否则,['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']]]]]]