2

i have such config file:

#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 {

}

And i need to find all subnet blocks. The problem is subnet block can contain host blocks (with curly brackets). And i cant construct regexp to match those.

So the result should be:
1. subnet 10.8.140.2 netmask 255.255.255.255 { ... host {...} host{...}}
2. subnet 20.8.110.1 netmask 255.255.255.255 { ... }

Vololodymyr
  • 1,996
  • 5
  • 26
  • 45

2 Answers2

3

You didn't named your programming language. Here comes an example using a recursive pattern in PHP (PCRE):

<?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 uses Perl compatible regexes, you can use the same pattern in Perl or other languages which use the same engine and support recursion.

Btw, the syntax higlighter seems to have fun with the pattern, but it is not a syntax error.

Online example

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
1

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

But in you case, if the subnet blocks follow the skeleton subnet|host|option the deepness is finite.

By brute-force here what I got:

((|\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)*)*\})

Ugly AF. You can test it here.

I use (|\s|\n)* too often, I actually allow no space between subnet and first ip : subnet10.4.4.2 which is bad.

But you may allow no space between host-name and opening bracket, like in your code: host example{.

Community
  • 1
  • 1
Orace
  • 7,822
  • 30
  • 45