
Necesito una expresión regular para capturar registros de registro de host DHCP
Necesito analizar a través de undhcpd.confarchivo, para todas las reservas de host y, si es posible, capturarlos en un archivo o matriz Bash. Entonces, si una reserva de anfitrión se define de la siguiente manera,
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";
}
Salida a archivo o matriz 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
Si falta uno de los tres parámetros, déjelo en blanco.
Incluso si la expresión debe aplicarse línea por línea, sigue siendo aceptable. Puedo ajustar la expresión mediante un script Bash que lee el archivo de configuración línea por línea, por supuesto.
Respuesta1
Como parse_dhcp.awk
si
#!/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()}
entonces
awk -f parse_dhcp.awk dhcp.conf
Más oscuramente, ese archivo tiene una sintaxis Tcl válida, por lo que solo necesitamos escribir el DSL para poder evaluar el archivo como un script 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
y
tclsh parse_dhcp.tcl dhcp.conf
Respuesta2
Las siguientes líneas simples de Perl parecen casi generar lo que desea:
perl -ane 'print $F[-1] =~ s/[";]//gr unless /[{}]/; print /^$/ ? "\n" : " "'
pero me temo que la entrada puede contener secciones que deseas omitir por completo, por lo que se necesitan más ajustes:
perl -ane 'if (/host/ .. /}/) {
print $F[-1] =~ s/[";]//gr unless /[{}]/;
print /}/ ? "\n" : " "
}'
lo que significa
- si estamos entre líneas que contienen
host
y}
, procesamos la entrada; de lo contrario, la omitimos. - Si la línea actual no contiene rizos, imprimimos la última palabra, eliminando el punto y coma y las comillas dobles.
- si la línea contiene una llave de cierre, imprimimos una nueva línea; de lo contrario, un espacio.
Respuesta3
Entonces vi gente respondiendo con soluciones diferentes y creativas. Como entusiasta de las expresiones regulares, intenté responder con expresiones regulares según fuera necesario.
Resulta que su muestra no es un documento bien formado debido a que falta un punto y coma en la declaración de prueba del host.
Verá, hay un error de sintaxis allí que invalida dos expresiones perfectamente razonables dentro de la prueba del host de declaración: dirección fija y opción.
Si desea trabajar con documentos bien formados y este ejemplo fue un error, puede utilizar:
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*\}
La cadena de sustitución será entonces:
\2, \5, \7
Por otro lado, si necesita abordar documentos a los que les falta punto y coma, coloque un signo de interrogación después de cada punto y coma que necesite convertir en opcional.
Puede probar sus opciones enhttps://regex101.com/
Déjame saber si cometí un error. Buena suerte.