web-dev-qa-db-fra.com

Comment définir le contexte après grep sur "jusqu'à la prochaine ligne vide"?

Avec grep, je sais comment définir le contexte pour un nombre fixe de lignes. Est-il possible d'afficher un contexte basé sur une condition de chaîne arbitraire, comme définir après-contexte sur "jusqu'à la ligne vide suivante"?

Ou peut-être une autre combinaison d'outils?

Fondamentalement, j'ai un fichier journal de lignes contiguës, avec des lignes vierges séparant les "événements". Je souhaite rechercher une chaîne dans le fichier journal, mais afficher l'ensemble de l'événement ....

30
pixelearth

Il semble que vous ayez besoin de sed:

sed -n '/pattern/,/^$/p' file

Ne pas imprimer par défaut (-n). Pour les lignes correspondant à /pattern/ jusqu'à une ligne vide /^$/, imprimez.

28
Jonathan Leffler

Une solution simple est:

awk '/pattern/' RS= input-file

Définir RS sur la chaîne vide oblige awk à traiter les lignes vides comme séparateur d'enregistrement, et la règle simple /pattern/ force awk à imprimer tout enregistrement correspondant au modèle, qui peut être toute expression régulière étendue.

20
William Pursell

Voici une solution awk (testée), séparée sur plusieurs lignes pour plus de lisibilité:

awk '/pattern/ {do_print=1}
     do_print==1 {print}  
     NF==0 {do_print=0}' input_file

Ce script imprimera également la ligne vierge pour faciliter la séparation visuelle des différents blocs correspondants. Si vous ne voulez pas la ligne vide, permutez les 2 lignes do_print==1 {print} et NF==0 {do_print=0}

Explication:

  • awk: invoque l'outil awk - il évalue la ligne d'entrée une par une de manière séquentielle.
  • '...'.: tout ce qui est entouré par les guillemets simples est donné à awk sous forme d'instructions. Dans ce cas, nous exécutons les instructions citées sur chaque ligne.
  • /pattern/ {do_print=1}: chaque fois qu'une ligne contient "pattern", activez l'indicateur do_print
  • do_print==1 {print}: si le drapeau do_print est activé, affiche la ligne en cours.
  • NF==0 {do_print=0}: NF signifie Nombre de champs. awk délimite chaque ligne par des espaces et des tabulations par défaut pour fractionner une ligne en champs. Dans ce cas trivialement, une ligne vide n'a pas de champs - nous désactivons donc l'indicateur do_print pour arrêter l'impression lorsque nous voyons une ligne avec NF == 0
8
sampson-chen

Personnellement, j’aime bien la réponse de @William Pursell car le contexte précédent est souvent utile (par exemple, lorsqu’on cherche des objets dans des fichiers ini). Si vous ne voulez réellement que le contexte after avec awk, vous pouvez le faire:

$ cat demo.ini 
[foo]
aaa = 1
bbb = 2
ccc = 3

[bar]
eee = 8
fff = 0
ggg = 1

[baz]
xxx = 1
yyy = 0
zzz = 2
$ awk '/bar/,/^$/' demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1

$ awk '/fff/,/^$/' demo.ini 
fff = 0
ggg = 1

$

Comparez avec la version RS=:

$ awk '/bar/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
$ awk '/fff/' RS= demo.ini 
[bar]
eee = 8
fff = 0
ggg = 1
0
htaccess