与pyparsing匹配的简单嵌套表达式

den*_*ger 4 python parsing pyparsing

我想匹配一个看起来像这样的表达式:

(<some value with spaces and m$1124any crazy signs> (<more values>) <even more>)
Run Code Online (Sandbox Code Playgroud)

我只是想沿着圆括号 () 拆分这些值。目前,我可以减少 s-expression 示例中的 pyparsing 开销,这非常广泛且无法理解(恕我直言)。

我尽可能使用该nestedExpr语句,将其减少为一行:

import pyparsing as pp
parser = pp.nestedExpr(opener='(', closer=')')
print parser.parseString(example, parseAll=True).asList()
Run Code Online (Sandbox Code Playgroud)

结果似乎也被分割在空白处,这是我不想要的:

  skewed_output = [['<some',
  'value',
  'with',
  'spaces',
  'and',
  'm$1124any',
  'crazy',
  'signs>',
  ['<more', 'values>'],
  '<even',
  'more>']]
expected_output = [['<some value with spaces and m$1124any crazy signs>' 
['<more values>'], '<even more>']]
best_output = [['some value with spaces and m$1124any crazy signs' 
['more vlaues'], 'even more']]
Run Code Online (Sandbox Code Playgroud)

或者,我很乐意指出我可以阅读一些易于理解的介绍,以了解如何包含更详细的解析器(我想提取 < > 括号之间的值并匹配它们(请参阅best_output),但我总是可以string.strip()他们之后。

提前致谢!

yep*_*ons 6

Pyparsing 的nestedExpr接受contentignoreExpr参数指定什么是 s-expr 的“单个项目”。你可以通过QuotedString这里。不幸的是,我不太了解文档中两个参数之间的区别,但是一些实验表明以下代码应该满足您的要求:

import pyparsing as pp

single_value = pp.QuotedString(quoteChar="<", endQuoteChar=">")
parser = pp.nestedExpr(opener="(", closer=")",
                       content=single_value,
                       ignoreExpr=None)

example = "(<some value with spaces and m$1124any crazy signs> (<more values>) <even more>)"
print(parser.parseString(example, parseAll=True))
Run Code Online (Sandbox Code Playgroud)

输出:

[['some value with spaces and m$1124any crazy signs', ['more values'], 'even more']]
Run Code Online (Sandbox Code Playgroud)

它期望列表以 开头(,以 结尾),并包含一些可选的以空格分隔的列表或带引号的字符串,每个带引号的字符串应以 开头<,以 结尾>并且不包含<在里面。

您可以更多地使用contentignoreExpr参数来找出使content=None, ignoreExpr=single_value解析同时接受带引号和不带引号的字符串(并用空格分隔未带引号的字符串):

import pyparsing as pp

single_value = pp.QuotedString(quoteChar="<", endQuoteChar=">")
parser = pp.nestedExpr(opener="(", closer=")", ignoreExpr=single_value, content=None)

example = "(<some value with spaces and m$1124any crazy signs> (<more values>) <even m<<ore> foo (foo) <(foo)>)"
print(parser.parseString(example, parseAll=True))
Run Code Online (Sandbox Code Playgroud)

输出:

[['some value with spaces and m$1124any crazy signs', ['more values'], 'even m<<ore', 'foo', ['foo'], '(foo)']]
Run Code Online (Sandbox Code Playgroud)

一些问题悬而未决:

  1. 为什么pyparsing忽略连续列表项之间的空格?
  2. 是什么区别content,并ignoreExpr和时应该使用他们每个人的?

  • 通常,pyparsing 将空格视为可忽略的分隔符。您是否在此处找到了 pyparsing 的在线帮助?https://pythonhosted.org/pyparsing/pyparsing-module.html#nestedExpr 。文档在过去一年中得到了极大的增强,增加了大约 1000 行内联示例。 (2认同)