Comment imprimer toutes les lignes ne contenant pas de string avec les lignes adjacentes?

J'essaie de m'occuper de cette tâche. Je veux de la sortie suivante, pour exclure toutes les lignes qui contiennent Auto-installed: 1 et les 2 lignes avant. Je pensais naïvement que la grep -v -B2 ssortingng résoudrait le problème … inutile de le dire, ne fait qu'empirer les choses.

C'est le contenu:

 Package: libopencore-amrwb0 Architecture: amd64 Auto-Installed: 1 Package: transfig Architecture: amd64 Auto-Installed: 0 Package: xfig-libs Architecture: amd64 Auto-Installed: 1 Package: xaw3dg Architecture: amd64 Auto-Installed: 0 

Et voici à quoi ressemblent les résultats:

 Package: transfig Architecture: amd64 Auto-Installed: 0 Package: xaw3dg Architecture: amd64 Auto-Installed: 0 

(note, les lignes vides ne sont pas affichées, si elle n'affiche pas de lignes vides est un plus, mais n'est pas obligatoire, les résultats doivent également inclure les packages dont les valeurs auto-installées sont 0)

Je sais que je peux faire correspondre les sauts de ligne mais soit finir par ne rien imprimer ou imprimer tout mais les lignes se casse entre les deux.

Toute solution est acceptable, il ne doit pas nécessairement être grep ( il peut même s'agir d'emacs ).

Je ne suis pas sûr de la structure de vos données, mais si c'est comme vous le montrez, que diriez-vous de ce qui suit:

 grep -B2 'Auto-Installed: [^1]' 

Cela suppose que chaque strophe inclut une ligne Auto-Installed , ce qui peut ne pas être correct.

Voici un programme awk qui, je pense, fait exactement ce que vous avez demandé.

 awk 'BEGIN{deleted=3} !deleted{printf "%s",l[NR%3]} deleted {--deleted} {l[NR%3]=/./?$0"\n":$0} /Auto-Installed: 1/{deleted=3} END{for(i=NR+deleted;i<NR+3;++i)printf "%s",l[i%3]}' 

Je pense que ça va te faire

 sed ':a $!N # slurp /Auto-Installed: 1/s/.*// # kill all buffered on match $!{/\n.*\n/{P;D}} # P/D any third line, D cycles w/o read $!ba # if no P/D, cycle w/o read anyway ' 

Au lieu d'essayer de les exclure, pourquoi ne pas simplement sélectionner les lignes opposées, qui sont ce que vous voulez de toute façon?

 $ grep -B 2 "Auto-Installed: 0" data.txt Package: transfig Architecture: amd64 Auto-Installed: 0 

En excluant les sections qui ont "Auto-Installé: 1"

Si vous souhaitez utiliser grep mais en utilisant votre logique pour aborder le problème où vous excluez les sections qui contiennent «Auto-Installed: 1», je n'ai pas trouvé cette approche en utilisant la fonction PCRE dans GNU grep.

 $ grep -B2 -P 'Auto-Installed: (?!1)' data.txt 

Exemple

 $ grep -B2 -P 'Auto-Installed: (?!1)' data.txt Package: transfig Architecture: amd64 Auto-Installed: 0 

Ce qui précède utilise la fonction lookahead de Perl , (?!..) . Cela nous permet de faire la search de lignes qui ne contiennent pas une valeur de 1, après l' Auto-Installed: Nous -B2 alors à grep d'afficher 2 lignes ( -B2 ) avant puis "match".

Ce que vous avez est en fait des loggings séparés par des lignes vides. Plutôt que de coder un parsing fragile qui dépend de l'ordre et du nombre de lignes, utilisez un outil comme awk ou perl pour traiter les loggings séparés par des lignes vides (mode paragraphe).

 awk -F '' '! /^Auto-Installed: 1$/' 

Et voici la méthode Perl obligatoire:

 perl -000ne 'print unless /Auto-Installed: 1/' file 

La magie est le -000 , cela active le mode paragraphe de Perl qui le divise en paragraphes. En d'autres termes, les loggings sont séparés par deux ou plusieurs caractères consécutifs.

Cela va également imprimer la ligne vide entre les inputs, pour se débarrasser de cela, vous pourriez courir

 perl -000ne 'print unless /Auto-Installed: 1/' file | grep .