擷取 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/

如果我犯了錯誤,請告訴我。祝你好運。

相關內容