【问题标题】:Non greedy parsing with pyparsing使用 pyparsing 进行非贪婪解析
【发布时间】:2011-08-12 08:27:14
【问题描述】:

我正在尝试使用 pyparsing 解析一行。该行由许多(键,值)组成。我想得到的是(键,值)的列表。一个简单的例子:

ids = 12 fields = name

应该是这样的:[('ids', '12'), ('fields', 'name')]

一个更复杂的例子:

ids = 12, 13, 14 fields = name, title

应该产生类似:[('ids', '12, 13, 14'), ('fields', 'name, title')]

PS:结果列表中的元组只是一个示例。它可以是一个 dict 或另一个列表或其他任何东西,这并不重要。

但是到目前为止,无论我尝试过什么,我都会得到如下结果: [('ids', '12 fields')]

考虑到它也是价值的一部分,Pyparsing 正在吃下一个键。

这是一个示例代码:

import pyparsing as P

key = P.oneOf("ids fields")
equal = P.Literal('=')
key_equal = key + equal
val = ~key_equal + P.Word(P.alphanums+', ')

gr = P.Group(key_equal+val)
print gr.parseString("ids = 12 fields = name")

有人可以帮助我吗?谢谢。

【问题讨论】:

    标签: python parsing grammar pyparsing


    【解决方案1】:

    第一个问题出在这一行:

    val = ~key_equal + P.Word(P.alphanums+', ')
    

    这表明该部分匹配任何字母数字序列,后跟文字 ', ',但它匹配任何字母数字字符序列,','' '

    你想要的是:

    val = ~key_equal + P.delimitedList(P.Word(P.alphanums), ", ", combine=True)
    

    第二个问题是你只解析了一个键值对:

    gr = P.Group(key_equal+val)
    

    相反,您应该尽可能多地解析:

    gr = P.Group(P.OneOrMore(key_equal+val))
    

    所以正确的解决方案是:

    >>> import pyparsing as P
    >>> key = P.oneOf("ids fields")
    >>> equal = P.Literal('=')
    >>> key_equal = key + equal
    >>> val = ~key_equal + P.delimitedList(P.Word(P.alphanums), ", ", combine=True)
    >>> gr = P.OneOrMore(P.Group(key_equal+val))
    >>> print gr.parseString("ids = 12, 13, 14 fields = name, title")
    [['ids', '=', '12, 13, 14'], ['fields', '=', 'name, title']]
    

    【讨论】:

    • PS:稍微修改了您的帖子。我用你的解决方案得到了更好的结果。问题是我只得到第一部分而不是以下部分。我得到 [('ids', '12,13,14')]。我想得到 [('ids', '12,13,14'), ('fields', 'name,title')]
    • @Oli:感谢您的关注。我为您的第二个问题添加了解决方案。
    • 非常感谢。正是我需要的。
    • @Oli:当心,我在你评论的版本中犯了一个小错误。 (它将所有内容放在同一个列表中,而不是对单独的对进行分组)。此问题现已修复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    • 2015-05-29
    相关资源
    最近更新 更多