我需要一个正则表达式来捕获 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/
如果我犯了错误,请告诉我。祝你好运。