
Ich brauche einen regulären Ausdruck, um DHCP-Hostregistrierungsdatensätze zu erfassen
Ich muss einedhcpd.confDatei, für alle Hostreservierungen, und wenn möglich, diese in einer Datei oder einem Bash-Array erfassen. Wenn also eine Hostreservierung wie folgt definiert ist,
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";
}
Ausgabe in eine Datei oder ein Bash-Array ...
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
Wenn einer der drei Parameter fehlt, lassen Sie ihn leer.
Auch wenn der Ausdruck zeilenweise angewendet werden muss, ist das noch akzeptabel. Ich kann den Ausdruck natürlich über ein Bash-Skript umschließen, das die Konfigurationsdatei zeilenweise liest.
Antwort1
Mit parse_dhcp.awk
als
#!/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()}
Dann
awk -f parse_dhcp.awk dhcp.conf
Noch undurchsichtiger ist, dass diese Datei eine gültige Tcl-Syntax aufweist, wir müssen also nur die DSL schreiben, damit wir die Datei als Tcl-Skript auswerten können:
#!/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
Und
tclsh parse_dhcp.tcl dhcp.conf
Antwort2
Die folgende einzeilige Perl-Ausgabe scheint fast das auszugeben, was Sie möchten:
perl -ane 'print $F[-1] =~ s/[";]//gr unless /[{}]/; print /^$/ ? "\n" : " "'
ich fürchte jedoch, dass die Eingabe Abschnitte enthalten kann, die Sie vollständig überspringen möchten. Daher sind weitere Optimierungen erforderlich:
perl -ane 'if (/host/ .. /}/) {
print $F[-1] =~ s/[";]//gr unless /[{}]/;
print /}/ ? "\n" : " "
}'
was bedeutet
- Wenn wir uns zwischen Zeilen befinden, die
host
und enthalten}
, verarbeiten wir die Eingabe, andernfalls überspringen wir sie. - Wenn die aktuelle Zeile keine Anführungszeichen enthält, drucken wir das letzte Wort aus, nachdem wir Semikolons und Anführungszeichen entfernt haben
- Wenn die Zeile eine schließende geschweifte Klammer enthält, drucken wir eine neue Zeile, andernfalls ein Leerzeichen.
Antwort3
Ich habe gesehen, dass die Leute mit unterschiedlichen und kreativen Lösungen geantwortet haben. Als Regex-Enthusiast habe ich versucht, bei Bedarf mit regulären Ausdrücken zu antworten.
Es stellt sich heraus, dass Ihr Beispiel aufgrund des fehlenden Semikolons in der Testanweisung des Hosts kein wohlgeformtes Dokument ist.
Sie sehen, hier liegt ein Syntaxfehler vor, der zwei völlig sinnvolle Ausdrücke innerhalb der Anweisung „Host Test“ ungültig macht: „Fixed-Address“ und „Option“.
Wenn Sie mit wohlgeformten Dokumenten arbeiten möchten und dieses Beispiel ein Fehler war, können Sie Folgendes verwenden:
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*\}
Die Ersetzungszeichenfolge lautet dann:
\2, \5, \7
Wenn Sie hingegen Dokumente adressieren müssen, in denen Semikolons fehlen, setzen Sie nach jedem Semikolon, das Sie optional machen möchten, ein Fragezeichen.
Sie können Ihre Optionen testen inhttps://regex101.com/
Sagen Sie mir Bescheid, wenn ich einen Fehler gemacht habe. Viel Glück.