web-dev-qa-db-fra.com

Comment puis-je traiter des enregistrements multilignes avec awk dans un script bash?

example.txt est ci-dessous

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

J'utilise le script bash et disons que je veux rechercher un restaurant par son nom dans le fichier ci-dessus. Demandez à l'utilisateur d'entrer le nom du restaurant et il devrait imprimer les informations concernant ce restaurant (5 lignes).

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

Je sais que la ligne de code ci-dessus imprimera toute la ligne correspondant au modèle "McDonalds" et "KFC", mais imprimera simplement la 1ère ligne du fichier texte, mais pas le reste des informations concernant ce restaurant. Comment puis-je lui dire d'imprimer toutes les informations (5 lignes) à partir de la seule entrée utilisateur du nom du restaurant?

13
Selena Gomez

Avec awk, vous pouvez changer le séparateur record. Par défaut, c'est une nouvelle ligne, chaque ligne du fichier est donc un enregistrement. Si vous définissez la variable RS sur la chaîne vide, awk considérera que les enregistrements sont séparés par des lignes vides:

awk -v name="KFC" -v RS="" '$0 ~ "Restaurant: " name' example.txt
11
glenn jackman

Utilisation de 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

Explication

C’est la fonction sed de base, vous pouvez vous référer SCRIPTS UTILES À UNE LIGNE POUR SED

# print section of file between two regular expressions (inclusive)
sed -n '/Iowa/,/Montana/p'             # case sensitive
3
BMW
$ 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

La commande ci-dessus va obtenir et imprimer les 4 lignes consécutives avec la ligne en cours car elle a été introduite dans une boucle for.Le motif de recherche $2=="KFC" permet d'obtenir une ligne particulière à partir de plusieurs lignes.

1
Avinash Raj

Une autre solution possible:

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

Il suffit d’imprimer de la ligne contenant le nom souhaité à la dernière ligne contenant Word Phone(en supposant bien sûr que toutes les entrées suivent le même modèle et que Phonesera toujours le dernier enregistrement)

$> 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 nous voulions compliquer un peu les choses, nous pourrions imprimer exactement 5 lignes après le match, comme ceci:

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

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

La variable stopne sera pas définie, donc NR<=stop n'imprimera rien, jusqu'à ce que la partie /McDonalds/{stop=NR+5;} définisse réellement la variable, et cela ne se produira que lorsque nous aurons trouvé la correspondance.

0