捕获 DHCP 主机注册记录的正则表达式是什么?

捕获 DHCP 主机注册记录的正则表达式是什么?

我需要一个正则表达式来捕获 DHCP 主机注册记录

我需要解析dhcpd配置文件文件,用于所有主机预留,如果可能的话将其捕获到文件或 Bash 数组中。因此,如果主机预留定义如下,

    host Service-Ethernet {
        hardware ethernet 11:11:11:11:11:11;
        fixed-address 192.168.0.3;
        option host-name "service";
    }

    host Service-Wifi {
        hardware ethernet 22:22:22:22:22:22;
        fixed-address 192.168.0.4;
    }

    host Test {
        hardware ethernet 33:33:33:33:33:33;
        fixed-address 192.168.0.5
        option host-name "test";
    }

输出到文件或 Bash 数组...

11:11:11:11:11:11, 192.168.0.3, service
22:22:22:22:22:22. 192.168.0.4,
, 192.168.0.5, test

如果三个参数之一缺失,请将其留空。

即使表达式必须逐行应用,这仍然是可以接受的。当然,我可以通过 Bash 脚本包装表达式,逐行读取配置文件。

答案1

parse_dhcp.awk作为

#!/usr/bin/env awk -f

function output() {
    printf "%s, %s, %s\n", hw, fa, opt
}

$1 == "host" {
    if (NR > 1) output()
    hw = fa = opt = ""
    next
}

{sub(/;$/, "")}
$1 == "hardware"      {hw = $NF}
$1 == "fixed-address" {fa = $NF}
$1 == "option"        {opt = $NF; gsub(/"/, "", opt)}

END {output()}

然后

awk -f parse_dhcp.awk dhcp.conf

更晦涩的是,该文件是有效的 Tcl 语法,因此我们只需要编写 DSL,以便我们可以将该文件作为 Tcl 脚本进行评估:

#!/usr/bin/env tclsh

proc host {name data} {
    global vars
    array set vars {hardware "" fixed-address "" option ""}
    eval $data
    puts "$vars(hardware), $vars(fixed-address), $vars(option)"
}

proc unknown {cmd args} {
    global vars
    set vars($cmd) [lindex $args end]
}

set file [lindex $argv 0]
source $file

tclsh parse_dhcp.tcl dhcp.conf

答案2

下面的 Perl 一行似乎几乎输出了你想要的内容:

perl -ane 'print $F[-1] =~ s/[";]//gr unless /[{}]/; print /^$/ ? "\n" : " "'

但我担心输入可能包含您想要完全跳过的部分,因此需要更多调整:

perl -ane 'if (/host/ .. /}/) {
               print $F[-1] =~ s/[";]//gr unless /[{}]/;
               print /}/ ? "\n" : " "
           }'

意思是

  • 如果我们位于包含host和 的行之间},我们处理输入,否则我们跳过它。
  • 如果当前行不包含花括号,我们将打印最后一个单词,并从中删除分号和双引号
  • 如果该行包含右大括号,则打印换行符,否则打印空格。

答案3

所以,我看到人们用不同的、创造性的解决方案来回答。作为一名正则表达式爱好者,我尝试按要求用正则表达式来回答。

事实证明,由于主机 Test 语句中缺少分号,您的示例不是格式良好的文档。

您会看到,那里有一个语法错误,它使语句主机 Test 中的两个完全合理的表达式无效:固定地址和选项。

如果您想使用格式良好的文档并且此示例是错误的,那么您可以使用:

host\s+[\w\-]+\s*\{(\s+hardware\s+ethernet\s+(([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2});)?(\s*fixed-address\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3});)?(\s*option\s+host-name\s+"(.*?)";)?\s*\}

替换字符串将是:

\2, \5, \7

另一方面,如果您需要解决缺少分号的文档,请在每个需要转为可选的分号后加上问号。

您可以测试您的选择https://regex101.com/

如果我犯了错误,请告诉我。祝你好运。

相关内容