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

13

exemplo.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 queira procurar um restaurante pelo nome do arquivo acima. Peça a entrada do usuário para o nome do restaurante e deve imprimir as informações sobre esse restaurante (5 linhas).

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

Eu sei que a linha de código acima irá imprimir toda a linha que corresponde ao padrão "McDonalds" e "KFC", mas que imprimirá apenas a primeira 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?

    
por Selena Gomez 27.03.2014 / 03:43

5 respostas

11

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

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt
    
por glenn jackman 27.03.2014 / 03:51
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 função sed básica, você pode consultar SCRIPTS DE LINHA ÚTEIS PARA O SED

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
    
por BMW 27.03.2014 / 05:22
1
$ 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 junto com a linha atual porque foi alimentado em um loop for. O padrão de busca $2=="KFC" ajudará a obter uma linha particular das múltiplas linhas.

    
por Avinash Raj 27.03.2014 / 05:26
0

Outra solução possível:

awk 'BEGIN{FS="\n";RS="\n\n"}{if($1=="KFC")print $0}' example.txt
    
por Faisal 09.04.2016 / 16:42
0

É suficiente imprimir da linha que contém o nome desejado até a última linha contendo a palavra Phone (supondo, é claro, que todas as entradas sigam o mesmo padrão e sempre terão Phone como 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 variável stop não será definida, portanto, NR<=stop não imprimirá nada, até que /McDonalds/{stop=NR+5;} parte realmente defina a variável, e isso só acontecerá quando encontrarmos a correspondência.

    
por Sergiy Kolodyazhnyy 09.04.2016 / 17:23

Tags