Como processar registros de várias linhas com awk em um script bash?

13

example.txt está abaixo

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

Estou usando o script bash e digamos que eu quero procurar um restaurante pelo nome no arquivo acima. Peça à entrada do usuário o nome do restaurante e ele deverá imprimir as informações sobre esse restaurante (5 linhas).

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

Eu sei que a linha de código acima imprimirá toda a linha que corresponde ao padrão "McDonalds" e "KFC", mas que apenas imprimirá a 1ª linha do arquivo de texto, mas não o restante das informações sobre esse restaurante. Como posso dizer para imprimir todas as informações (5 linhas) apenas da entrada do usuário do nome do restaurante?

Selena Gomez
fonte

Respostas:

11

Com o awk, você pode alterar o separador de registros . Por padrão, é uma nova linha, portanto, cada linha do arquivo é um registro. Se você definir a RSvariável como uma sequência vazia, o awk considerará os registros separados por linhas em branco:

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt
Glenn Jackman
fonte
Eu não entendo sua pergunta. É bastante vago. É a tarefa ou o uso que você não recebe?
Glenn Jackman
3

Usando 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

Explicação

Esta é a sedfunção básica , você pode consultar SCRIPTS ÚNICOS ÚTEIS PARA SED

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
BMW
fonte
Adicione a explicação.
BMW
Mas por que a edição sugerida foi rejeitada? Eu não mudei a resposta. Acabei de melhorar a formatação.
daisy
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

O comando acima obterá e imprimirá as 4 linhas consecutivas, juntamente com a linha atual, porque foi alimentada em um loop for. O padrão de pesquisa $2=="KFC"ajudará a obter uma linha específica das várias linhas.

Avinash Raj
fonte
0

Outra solução possível:

awk 'BEGIN{FS="\n";RS="\n\n"}{if($1=="KFC")print $0}' example.txt
Faisal
fonte
O {if($1=="KFC")print $0}podem ser condensados apenas $1 == "KFC", uma vez que a ação padrão para uma condição verdadeira é imprimir o registro.
Muru
0

É suficiente imprimir da linha que contém o nome que você quer, até a última linha que contém a palavra Phone(supondo que todas as entradas sigam o mesmo padrão e sempre terão Phonecomo registro 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

Se quiséssemos complicar um pouco, poderíamos imprimir exatamente 5 linhas após a partida, assim:

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

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

A stopvariável não será definida, portanto NR<=stop, não imprimirá nada, até que a /McDonalds/{stop=NR+5;}parte realmente defina a variável, e isso só acontecerá quando encontrarmos a correspondência.

Sergiy Kolodyazhnyy
fonte