使用 Optional() 子类的 Pyparsing 语法
Pyparsing grammar with Optional() subclass
我正在解析具有一对标签:值的路由器输出。值可以省略。为了解析它,我使用了具有默认值的 Optional() 子类。为什么解析器忽略它(和 ~White 在价值评估中)?
我的代码
from pyparsing import *
if __name__ == '__main__':
text = '''
Peer AS : 65000 Peer Port : 0
Peer Address : 100.8.0.1
Local AS : 65000 Local Port : 0
Remote Capability :
Local AddPath Capabi*: Disabled
Remote AddPath Capab*: Send - None
Graceful Restart : Disabled
Import Policy : None Specified / Inherited
Export Policy : Access_EXP
'''
label_word = Word(printables, excludeChars=':')
value_word = Word(printables)
separator = Optional('*') + ': '
label = Combine(OneOrMore(label_word | Suppress(White(' ', max=1)) + ~White())) + FollowedBy(separator)
value = Combine(ZeroOrMore(Word(printables) | White(' ', max=1) + ~White()))
attr_expr = label + Suppress(separator) + Optional(value, default='')
result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
print(result.dump())
结果
- ExportPolicy: 'Access_EXP'
- GracefulRestart: 'Disabled'
- ImportPolicy: 'None Specified / Inherited'
- LocalAS: '65000'
- LocalPort: '0'
- PeerAS: '65000'
- PeerAddress: '100.8.0.1'
- PeerPort: '0'
- RemoteAddPathCapab*: 'Send - None'
- RemoteCapability: 'Local AddPath Capabi*: Disabled'
问题
"RemoteCapability" 有一个问题,它有一个空值但被解析为下一个字符串(另一对标签:值)。如何解决?
当解析多个键值对时,值是可选的,通常必须使用否定先行作为多重解析器的一部分。也就是说,如果您首先检查它不是键,则该值只能是一个值。
您的解决方案是在 value
的定义中,首先检查您是否没有解析 label
- 如果是,那么解析器已经前进到下一个标签并且在那里对当前的没有价值。为此,只需在 ZeroOrMore 重复中添加 ~label
:
value = Combine(ZeroOrMore(~label + Word(printables) | White(' ', max=1) + ~White()))
有了这个改变,我现在得到了你想要的解析输出:
- ExportPolicy: 'Access_EXP'
- GracefulRestart: 'Disabled'
- ImportPolicy: 'None Specified / Inherited'
- LocalAS: 65000
- LocalAddPathCapabi*: 'Disabled'
- LocalPort: 0
- PeerAS: 65000
- PeerAddress: '100.8.0.1'
- PeerPort: 0
- RemoteAddPathCapab*: 'Send - None'
- RemoteCapability: ''
我正在解析具有一对标签:值的路由器输出。值可以省略。为了解析它,我使用了具有默认值的 Optional() 子类。为什么解析器忽略它(和 ~White 在价值评估中)?
我的代码
from pyparsing import *
if __name__ == '__main__':
text = '''
Peer AS : 65000 Peer Port : 0
Peer Address : 100.8.0.1
Local AS : 65000 Local Port : 0
Remote Capability :
Local AddPath Capabi*: Disabled
Remote AddPath Capab*: Send - None
Graceful Restart : Disabled
Import Policy : None Specified / Inherited
Export Policy : Access_EXP
'''
label_word = Word(printables, excludeChars=':')
value_word = Word(printables)
separator = Optional('*') + ': '
label = Combine(OneOrMore(label_word | Suppress(White(' ', max=1)) + ~White())) + FollowedBy(separator)
value = Combine(ZeroOrMore(Word(printables) | White(' ', max=1) + ~White()))
attr_expr = label + Suppress(separator) + Optional(value, default='')
result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
print(result.dump())
结果
- ExportPolicy: 'Access_EXP'
- GracefulRestart: 'Disabled'
- ImportPolicy: 'None Specified / Inherited'
- LocalAS: '65000'
- LocalPort: '0'
- PeerAS: '65000'
- PeerAddress: '100.8.0.1'
- PeerPort: '0'
- RemoteAddPathCapab*: 'Send - None'
- RemoteCapability: 'Local AddPath Capabi*: Disabled'
问题
"RemoteCapability" 有一个问题,它有一个空值但被解析为下一个字符串(另一对标签:值)。如何解决?
当解析多个键值对时,值是可选的,通常必须使用否定先行作为多重解析器的一部分。也就是说,如果您首先检查它不是键,则该值只能是一个值。
您的解决方案是在 value
的定义中,首先检查您是否没有解析 label
- 如果是,那么解析器已经前进到下一个标签并且在那里对当前的没有价值。为此,只需在 ZeroOrMore 重复中添加 ~label
:
value = Combine(ZeroOrMore(~label + Word(printables) | White(' ', max=1) + ~White()))
有了这个改变,我现在得到了你想要的解析输出:
- ExportPolicy: 'Access_EXP'
- GracefulRestart: 'Disabled'
- ImportPolicy: 'None Specified / Inherited'
- LocalAS: 65000
- LocalAddPathCapabi*: 'Disabled'
- LocalPort: 0
- PeerAS: 65000
- PeerAddress: '100.8.0.1'
- PeerPort: 0
- RemoteAddPathCapab*: 'Send - None'
- RemoteCapability: ''