正则表达式查找配置文件中的所有子网块

时间:2015-04-08 08:37:14

标签: regex

我有这样的配置文件:

#DHCP Server Configuration file.

deny unknown-clients;

subnet 10.8.140.2 netmask 255.255.255.255 {
    host example{
            optian:param; 
    }
    host example2{
            option2:param2;
    }
}

subnet 20.8.110.1 netmask 255.255.255.255 {

}

我需要找到所有子网块。 问题是子网块可以包含主机块(带有花括号)。我不能构建正则表达式以匹配那些。

所以结果应该是:
1.子网10.8.140.2网络掩码255.255.255.255 {... host {...} host {...}}
2.子网20.8.110.1网络掩码255.255.255.255 {...}

2 个答案:

答案 0 :(得分:3)

你没有命名你的编程语言。下面是一个在PHP(PCRE)中使用recursive pattern的示例:

<?php

$conf = file_get_contents('/path/to/dhcp.conf');

# We use a recursive pattern, check the link I posted above
$pattern = '/(subnet.*?)?\{((?>[^{}]+)|(?R))*\}/';    

preg_match_all($pattern, $conf, $matches);

foreach($matches[0] as $match) {
    echo $match . PHP_EOL . PHP_EOL;
}

PHP使用 Perl兼容的正则表达式,您可以在Perl或使用相同引擎并支持递归的其他语言中使用相同的模式。

顺便说一下,语法高亮似乎对模式很有趣,但是语法错误。

Online example

答案 1 :(得分:1)

Regex can't be used to match nested pattern of arbitrarily deep nesting.

但在你的情况下,如果子网块遵循骨架 子网|主机|选项,则深度是有限的。

在这里蛮力我得到了:

((|\s|\n)*subnet(|\s|\n)*((\d{1,3}.){3}(\d{1,3}))(|\s|\n)*netmask(|\s|\n)*((\d{1,3}.){3}(\d{1,3}))(|\s|\n)*\{(|\s|\n)+((|\s|\n)+host(|\s|\n)*(\w+)(|\s|\n)*\{(|\s|\n)*(\w*)\:(\w*)\;(|\s|\n)*\}(|\s|\n)*)*\})

丑陋的AF。您可以对其进行测试here

我经常使用(|\s|\n)*,实际上我在子网和第一个ip:subnet10.4.4.2之间没有空格,这是不好的。

但您可能在主机名和左括号之间不允许使用空格,例如代码:host example{