Bash awk/sed extrae varias cadenas de una sola cadena grande usando palabras clave

Bash awk/sed extrae varias cadenas de una sola cadena grande usando palabras clave

Ayúdenme a descubrir cómo extraer varias subcadenas basadas en palabras clave. He estado luchando con diferentes métodos usando delimitadores.

Mi entrada:

Inventory for 30844-ap01 NAME: AP1800 , DESCR: Cisco Aironet 1800 Series (IEEE 802.11ac) Access Point PID: AIR-AP1832I-E-K9, VID: V03, SN: KWC21420CKU
Inventory for ckh.hq-ap99 NAME: AP2700 , DESCR: Cisco Aironet 2700 Series (IEEE 802.11n) Access Point PID: AIR-CAP2702I-E-K9, VID: V03, SN: FCW2007N0ZQ
Inventory for AP0042.6843.ab78 NAME:  , DESCR:  PID: AIR-CAP1702I-E-K9, VID: V, SN: FCZ201622NY

Salida deseada:

30844-ap01 AIR-AP1832I-E-K9 KWC21420CKU
ckh.hq-ap99 AIR-CAP2702I-E-K9 FCW2007N0ZQ
AP0042.6843.ab78 AIR-CAP1702I-E-K9 FCZ201622NY

La primera cadena es cualquier valor entre "Inventario para" y el siguiente espacio.

La segunda cadena es cualquier cosa entre "PID: " y la coma.

La tercera cadena es una cadena de 11 caracteres después de "SN:"

Respuesta1

Usando cualquier sed en cualquier shell en cada caja Unix:

$ sed 's/Inventory for \([^ ]*\).*PID: \([^,]*\).*SN:/\1 \2/' file
30844-ap01 AIR-AP1832I-E-K9 KWC21420CKU
ckh.hq-ap99 AIR-CAP2702I-E-K9 FCW2007N0ZQ
AP0042.6843.ab78 AIR-CAP1702I-E-K9 FCZ201622NY

Respuesta2

Creo que la mejor herramienta para este tipo de trabajos tiene greplas siguientes PCREcaracterísticas:

grep -Po '(?<=Inventory for )[^ ]+|(?<=PID: )[^,]+|(?<=SN: ).{11}' data

Pero esto tiene el inconveniente de imprimir cada coincidencia en líneas separadas:

30844-ap01
AIR-AP1832I-E-K9
KWC21420CKU
ckh.hq-ap99
AIR-CAP2702I-E-K9
FCW2007N0ZQ
AP0042.6843.ab78
AIR-CAP1702I-E-K9
FCZ201622NY

Así que cambiemos perly hagamos lo mismo:

perl -lne ' $i = $& if /(?<=Inventory for )[^ ]+/; $p = $& if /(?<=PID: )[^,]+/ ; $s = $& if /(?<=SN: ).{11}/; print join " ", $i, $p, $s' data

Imprimir:

30844-ap01 AIR-AP1832I-E-K9 KWC21420CKU
ckh.hq-ap99 AIR-CAP2702I-E-K9 FCW2007N0ZQ
AP0042.6843.ab78 AIR-CAP1702I-E-K9 FCZ201622NY

Respuesta3

Usando gawk:

awk '{a=b=c=$0;
gsub(/^.*Inventory for | .*$/,"",a);
gsub(/^.*PID: |,.*$/, "",b);
sub(/^.*SN: /,"",c); c=substr(c,1,11);
print a,b,c}' input

Las primeras tres variables y ase establecen en el registro de entrada actual ( ). Luego, la función incorporada cambia la expresión regular a una cadena vacía ( ). La expresión regular aquí usa alternancia y tiene dos patrones y . La alternancia permite un patrón alternativo en expresiones regulares con . Desde el inicio de la línea ( ) hasta se cambia a . Esto significa que se eliminan todos los caracteres desde el inicio de la línea hasta la primera cadena que queremos. De manera similar, desde el espacio (después de la primera cadena que queremos) hasta el final de la línea se cambia a . Del mismo modo tiene dos patrones alternativos y . Ambos se cambian a .bc$0gsub()""(/^.*Inventory for | .*$//^.*Inventory for // .*$/|gsub()^Inventory for""""/^.*PID: |,.*$//^.*PID: //,.*$/""

Luego sub()cambia /^.*SN: /a una cadena vacía y substr(c,1,11)toma una cadena de 11 caracteres de c.

información relacionada