
我需要一個正規表示式來擷取 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/
如果我犯了錯誤,請告訴我。祝你好運。