python - 用 textX 解析 dhcpd.conf
问题描述
我正在使用https://github.com/igordejanovic/textX解析dhcpd.conf
文件(不, https: //pypi.org/project/iscconf/ 对我不起作用,它在我的dhcpd.conf
文件上崩溃),特别是提取主机固定地址。
记录如下:
host example1 {
option host-name "example1";
ddns-hostname "example1";
fixed-address 192.168.1.181;
}
host example2 {
hardware ethernet aa:bb:ff:20:fa:13;
fixed-address 192.168.1.191;
option host-name "example2";
ddns-hostname "example2";
}
代码:
def get_hosts(s):
grammar = """
config: hosts*=host ;
host: 'host' hostname=ID '{'
(
('hardware ethernet' hardware_ethernet=/[0-9a-fA-F:]+/';')?
'fixed-address' fixed_address=/([0-9]{1,3}\.){3}[0-9]{1,3}/';'
('option host-name' option_host_name=STRING';')?
('ddns-hostname' ddns_hostname=STRING';')?
)#
'}'
;
"""
mm = metamodel_from_str(grammar)
model = mm.model_from_str(s)
for host in model.hosts:
print host.hostname, host.fixed_address
现在,我无法dhcpd.conf
用这个语法解析整个内容(显然,我得到了语法错误,因为文件中还有很多其他元素,语法没有考虑到);另一方面,我不想为这个文件构造完整的语法,因为我只需要提取特定类型的主机记录。
我当然可以使用正则表达式仅提取主机记录并单独解析它们,但我想知道是否有某种方法可以textX
只从文件中提取host
记录而忽略其余内容?
解决方案
textX 作者在这里。我不是SO的常客:)。您可以使用正则表达式匹配和正则表达式前瞻来消耗不需要的内容。这是一个完整的示例,即使有关键字也可以正确处理中间文本host
。config
如果前面没有单词,规则首先使用一个字符host
,并且由于零个或多个运算符而重复。当我们得到一个单词时host
,我们尝试匹配host
规则一次或多次并收集所有主机对象,如果规则至少有一个不成功(注意 的用法+=
),我们会使用单词host
并重复该过程。这可能会做得更好(性能更高),但你明白了。在执行此类操作时,最好知道 textX 默认使用空格,但您可以使用全局或按规则将其关闭noskipws
(请参阅文档)。
from textx import metamodel_from_str
def test_get_hosts():
grammar = r"""
config: ( /(?!host)./ | hosts+=host | 'host' )* ;
host: 'host' hostname=ID '{'
(
('hardware ethernet' hardware_ethernet=/[0-9a-fA-F:]+/';')?
'fixed-address' fixed_address=/([0-9]{1,3}\.){3}[0-9]{1,3}/';'
('option host-name' option_host_name=STRING';')?
('ddns-hostname' ddns_hostname=STRING';')?
)#
'}'
;
"""
conf_file = r"""
host example1 {
option host-name "example1";
ddns-hostname "example1";
fixed-address 192.168.1.181;
}
some arbitrary content in between
with word host but that fails to match host config.
host example2 {
hardware ethernet aa:bb:ff:20:fa:13;
fixed-address 192.168.1.191;
option host-name "example2";
ddns-hostname "example2";
}
"""
mm = metamodel_from_str(grammar)
model = mm.model_from_str(conf_file)
assert len(model.hosts) == 2
for host in model.hosts:
print(host.hostname, host.fixed_address)
if __name__ == "__main__":
test_get_hosts()
编辑:这里还有两个关于config
规则的想法:一个简单的:
config: ( hosts+=host | /./ )* ;
并且(可能)在尝试之前使用正则表达式引擎尽可能多地消耗性能host
:
config: ( /(?s:.*?(?=host))/ hosts*=host | 'host' )*
/(?s).*/;
推荐阅读
- c# - 在服务结构项目中部署选定的微服务
- webpack - 如何在电子主进程和渲染器进程之间共享配置?
- python - How to merge similar name to be come one name based on id, and Addition and substraction based on code
- hp-uft - 计划运行“用户已停止运行”
- python - How to do a Z-projection (like in ImageJ) using numpy arrays?
- wix - 我们能否知道与 msi 一起安装的功能的安装顺序
- c# - 如何使用 api 控制器在 .Net Core 2.* 中设置自定义 Webhook Sender 和 Reciever 实现
- elasticsearch - ElasticSearch 6.x / 7.x - 索引设计
- android - Multiple clickable links in TextView
- python - Add a table to sqlite database