¿Cómo puedo procesar registros de varias líneas con awk en un script bash?

13

ejemplo.txt está debajo

Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

Restaurant: 5 guys
City: Atlanta
State: Georgia
Address: 123 Peachtree Rd
Phone: 911

Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

Estoy usando el script bash y digamos que quiero buscar un restaurante por su nombre en el archivo de arriba. Solicite al usuario que ingrese el nombre del restaurante y debe imprimir la información sobre ese restaurante (5 líneas).

awk '/McDonalds/> /KFC/' example.txt

Sé que la línea de código anterior imprimirá toda la línea que coincida con el patrón "McDonalds" y "KFC", pero eso solo imprimirá la primera línea del archivo de texto pero no el resto de la información sobre ese restaurante. ¿Cómo puedo decirle que imprima toda la información (5 líneas) solo con la entrada del usuario del nombre del restaurante?

Selena Gómez
fuente

Respuestas:

11

Con awk, puede cambiar el separador de registros . Por defecto es una nueva línea, por lo que cada línea del archivo es un registro. Si establece la RSvariable en la cadena vacía, awk considerará que los registros están separados por líneas en blanco:

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt
Glenn Jackman
fuente
No entiendo tu pregunta. Es bastante vago. ¿Es la asignación o el uso que no obtienes?
Glenn Jackman
3

Utilizando sed:

$ sed -n '/KFC/,/^$/p' file
Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

$ sed -n '/McDo/,/^$/p' file
Restaurant: McDonalds
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

Explicación

Esta es una sedfunción básica , puede consultar SCRIPTS ÚTILES DE UNA LÍNEA PARA SED

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
BMW
fuente
Agrega la explicación.
BMW
Pero, ¿por qué se rechazó la edición sugerida? No cambié la respuesta. Acabo de mejorar el formato.
Margarita
2
$ awk '$2=="KFC" {print; for(i=1; i<=4; i++) { getline; print}}' example.txt

Restaurant: KFC
City: NYC
State: NY
Address: 123 Madison Square
Phone: 911

El comando anterior obtendrá e imprimirá las 4 líneas consecutivas junto con la línea actual porque se introdujo en un bucle for. El patrón de búsqueda $2=="KFC"ayudará a obtener una línea particular de varias líneas.

Avinash Raj
fuente
0

Otra posible solución:

awk 'BEGIN{FS="\n";RS="\n\n"}{if($1=="KFC")print $0}' example.txt
Faisal
fuente
Se {if($1=="KFC")print $0}puede condensar a solo $1 == "KFC", ya que la acción predeterminada para una condición verdadera es imprimir el registro.
muru
0

Es suficiente imprimir desde la línea que contiene el nombre que desea, hasta la última línea que contiene la palabra Phone(suponiendo, por supuesto, que todas las entradas sigan el mismo patrón y siempre tendrán un Phoneregistro final)

$> awk '/5 guys/,/Phone/' restaurants.txt                                     
Restaurant: 5 guys
City: Atlanta
State: Georgia
Address: 123 Peachtree Rd
Phone: 911
$> awk '/McDonalds/,/Phone/' restaurants.txt                                  
Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

Si quisiéramos complicarlo un poco, podríamos imprimir exactamente 5 líneas después del partido, así:

awk '/McDonalds/{stop=NR+5}; NR<=stop ' restaurants.txt                    

Restaurant: McDonalds 
City: Miami
State: Florida
Address: 123 Biscayne Blvd
Phone: 911

La stopvariable no se establecerá, por NR<=stoplo que no imprimirá nada, hasta que /McDonalds/{stop=NR+5;}parte realmente establezca la variable, y eso solo sucederá cuando encontremos la coincidencia.

Sergiy Kolodyazhnyy
fuente