【问题标题】:pyparsing with starting and ending string being the samepyparsing 开始和结束字符串相同
【发布时间】:2015-06-13 21:25:13
【问题描述】:

相关: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,并将{/} 替换为#/#,但它无法解析字符串。

【问题讨论】:

  • 也许只是在第 n 个 # 上替换为 #-# 之类的东西,然后通过 - 拆分或解析它。
  • 我没办法改变输入格式,可惜...
  • 您是想将所有级别分隔为字符串还是只是外部级别(例如,字符串的所有子级别都将作为该字符串包含在内)。那么删除字符串中的空格、制表符呢?
  • 好吧,起初我想到了你的后一个命题,然后我会递归地在输出字符串上重复该方法,所以第一步只会给我外部级别,其他嵌套块作为原始字符串,然后迭代这些会给我这些嵌套块的内容等。所以基本上,你的问题的答案是你的第一个命题,但我想保留块级别的痕迹。如果您明白我的意思,我不希望所有块都在一维列表中“展平”。

标签: python regex pyparsing


【解决方案1】:

不幸的是(对您而言),您的分组不仅取决于分隔的“#”字符,还取决于缩进级别(否则,['with','different','levels'] 将与前一组 ['and','some','others'] 处于同一级别)。解析缩进敏感的语法并不是 pyparsing 的强项——它可以完成,但并不令人愉快。为此,我们将使用 pyparsing 辅助宏 indentedBlock,它还要求我们定义一个列表变量,indentedBlock 可以将其用于其缩进堆栈。

请参阅下面代码中的嵌入式 cmets,了解如何使用 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']]]]]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-14
    • 2023-03-28
    • 2018-03-05
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-21
    相关资源
    最近更新 更多