pyparsing:每个使用Optional都有默认问题

时间:2015-07-16 08:27:40

标签: python default optional pyparsing

我需要解析configraion文件,其中可能省略配置命令(因此我想将Optionaldefault一起使用)并且没有特定的顺序(所以我必须使用Each) 。无论如何,让我们从有序的配置开始:

teststr = """
interface 4
  frames tagged
exit
interface 5
  pvid 17
exit
"""

portid = Word(nums)('portid')
pvid = Keyword('pvid').suppress() + Word(nums)('pvid')
frames = Keyword('frames').suppress() \
    + (Keyword('tagged') | Keyword('all'))

exit = Keyword('exit')

interface = Group(
    Keyword('interface') + portid  \
        + Optional(pvid) \
        + Optional(frames, default='all')('frames') \
        + exit
    )

interface_list = Group(interface + ZeroOrMore(interface))('interfaces')

res = interface_list.parseString(teststr)

for iface in res.interfaces:
    print '{}\n'.format(iface.dump())

这段代码给了我这个结果(没错,我相信---请注意frames第一部分设为tagged

['interface', '4', 'tagged', 'exit']
- frames: ['tagged']
- portid: 4

['interface', '5', '17', 'all', 'exit']
- frames: ['all']
- portid: 5
- pvid: 17

现在我想解析此配置,假设命令pvidframes可以按任意顺序排列,所以我想使用{{1} } 这样:

Each

现在我错了(我相信)结果:

interface = pp.Group(
    pp.Keyword('interface') + portid + (
            pp.Optional(pvid) 
          & pp.Optional(frames, default='all')('frames')
        ) + exit)

我希望['interface', '4', 'tagged', 'all', 'exit'] - frames: ['all'] - portid: 4 ['interface', '5', '17', 'all', 'all', 'exit'] - frames: ['all', 'all'] - portid: 5 - pvid: 17 返回与使用pyparsing运算符时相同的结果。我错了吗?有什么问题?

2 个答案:

答案 0 :(得分:0)

您使用的是什么版本的pyparsing?使用pyparsing 2.0.3,使用您的示例程序,我得到:

['interface', '4', 'tagged', 'exit']
- frames: ['tagged']
- portid: 4

['interface', '5', '17', 'all', 'exit']
- frames: ['all']
- portid: 5
- pvid: 17

答案 1 :(得分:0)

所以,我有2.0.3并将此补丁应用于它:

--- pyparsing-2.0.3.py  2015-07-16 17:30:16.705011488 +0300
+++ pyparsing-2.0.3-patched.py  2015-07-16 17:35:03.977015739 +0300
@@ -2811,6 +2811,9 @@
         self.defaultValue = default
         self.mayReturnEmpty = True

+        if self.defaultValue is not _optionalNotMatched:
+            self.mayReturnEmpty = False
+
     def parseImpl( self, instring, loc, doActions=True ):
         try:
             loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )

然后我更改了interface的定义:

interface = pp.Group(
    pp.Keyword('interface') + portid + (
            pp.Optional(pvid)
          & pp.Optional(frames('frames'), default='all')
        ) + exit)

这给了我最“直观”的结果,我会说:

['interface', '4', 'tagged', 'exit']
- frames: ['tagged']
- portid: 4

['interface', '5', '17', 'all', 'exit']
- frames: all
- portid: 5
- pvid: 17

该补丁不会破坏当前svn中的任何[更多]测试。无论如何,我不确定我知道自己在做什么,所以我仍在寻找答案。

@ paul-mcguire,对不起,升级到2.0.3并没有帮助我。

谢谢你。)