如何使用 python textx 排除标记来制作语法

问题描述 投票:0回答:1

我正在尝试解析网络设备配置文件,虽然我会浏览整个文件,但我不想包含文件的所有条款,而只想包含其中的一个子集。

所以假设配置文件如下:

bootfile abc.bin
motd "this is a
message for everyone to follow"
.
.
.
group 1
group 2
.
.
.
permit tcp ab.b.c.d b.b.b.y eq 222
permit tcp ab.b.c.d b.b.b.y eq 222
permit tcp ab.b.c.d b.b.b.y eq 222
.
.
.
interface a
  description this is interface a
  vlan 33 

interface b
  description craigs list
  no shut
  vlan 33
  no ip address
.
.
.

我只是想捕获接口线(按原样)以及描述和 VLAN 线 - 其他所有内容都将被忽略。界面内的内容将分为 2 个属性:有效和无效

所以语法看起来像这样:

Config[noskipsp]:
  interfaces *= !InterfaceDefinition | InterfaceDefinition
;

InterfaceDefinition:
  interface = intf
  valids *= valid
  invalids *= invalid
;

intf: /^interface .*\n/;
cmds: /^ (description|vlan) .*\n/;
invalid: /^(?!(interface|description|vlan) .*\n;

目标是获得一个Python接口数组,其中每个接口都有2个属性:valids和invalids,每个都是数组。有效数组将包含描述或 VLAN 条目,无效数组将包含其他所有内容。

有几个我似乎无法解决的挑战: 1-如何忽略所有其他不是接口定义的内容? 2- 如何确保所有接口最终都作为一个接口而不是另一个接口的 invalids 属性?

不幸的是 - 解析文本时的语法不会失败,但我对解析器如何遍历文本的理解似乎有问题,因为它在尝试读取通过“interface .*”部分的任何文本时会抱怨。

此外,目前我正在使用仅包含接口定义的文件进行显式测试,但目标是处理完整文件,仅针对接口,因此需要从语法方面丢弃所有其他内容。

python parsing configuration textx
1个回答
0
投票

你所做的通常被称为Island Grammars。您可以在 textX 中轻松做到这一点,并且可以轻松提取界面的实际结构。这是一种可能的解决方案:

from textx import metamodel_from_str

mmstr = r'''
Config:
    (
        /(?s)((?!interface).)*/   // <- consume everything till the keyword 'interface'
        interfaces=Interface
    )*
    /(?s).*/   // <- consume all content after the last interface
;

Interface:
    'interface' name=ID
    'description' description=/[^\n]*/
    /((?!vlan).)*/  // <- consume everything till the 'vlan'
    'vlan' vlan=INT;
'''

model_str = r'''
bootfile abc.bin
motd "this is a
message for everyone to follow"
.
.
.
group 1
group 2
.
.
.
permit tcp ab.b.c.d b.b.b.y eq 222
permit tcp ab.b.c.d b.b.b.y eq 222
permit tcp ab.b.c.d b.b.b.y eq 222
.
.
.
interface a
  description this is interface a
  vlan 33

interface b
  description craigs list
  no shut
  vlan 33
  no ip address
'''

mm = metamodel_from_str(mmstr)

model = mm.model_from_str(model_str)

for i in model.interfaces:
    print(i.name, i.description, i.vlan)

您始终可以将 textX 置于调试模式(通过传递

debug=True
)来查看解析过程并验证您的假设。

© www.soinside.com 2019 - 2024. All rights reserved.