grep inverser la recherche avec le contexte

Je veux filtrer plusieurs lignes avant et après une ligne correspondante dans un fichier.

Cela va supprimer la ligne que je ne veux pas:

$ grep -v "line that i don't want" 

Et cela imprimera les 2 lignes avant et après la ligne que je ne veux pas:

 $ grep -C 2 "line that i don't want" 

Mais quand je les combine, il ne filtre pas les 2 lignes avant et après la ligne que je ne veux pas:

 # does not remove 2 lines before and after the line I don't want: $ grep -v -C 2 "line that i don't want" 

Comment filtrer non seulement la ligne que je ne veux pas, mais aussi les lignes avant et après? Je suppose que sed serait mieux pour ça …

Edit: Je sais que cela pourrait se faire en quelques lignes de awk / Perl / Python / Ruby / etc, mais je veux savoir s’il y a un raccourci simple que je pourrais utiliser depuis la ligne de commande.

Essayez ceci:

 sed 'h;:b;$b;N;N;/PATTERN/{N;d};$b;P;D' inputfile 

Vous pouvez modifier le nombre de commandes N avant le modèle pour affecter le nombre de lignes à supprimer.

Vous pouvez générer par programme une chaîne contenant le nombre de N commandes:

 C=2 # corresponds to grep -C N=N for ((i = 0; i < C - 1; i++)); do N=$N";N"; done sed "h;:b;\$b;$N;/PATTERN/{N;d};\$b;P;D" inputfile 

Si les lignes sont toutes uniques, vous pouvez graver les lignes que vous souhaitez supprimer dans un fichier, puis utiliser ce fichier pour supprimer les lignes de l’original, par exemple

 grep -C 2 "line I don't want" < A.txt > B.txt grep -f B.txt A.txt 
 awk 'BEGIN{n=2}{a[++i]=$0} /dont/{ for(j=1;j<=i-(n+1);j++)print a[j]; for(o=1;o<=n;o++)getline; delete a} END{for(i in a)print a[i]} ' file 

Je pense que @ fxm27 a une excellente réponse bash-y.

J’appendais que vous pourriez résoudre ce problème d’une autre manière en utilisant egrep si vous connaissiez à l’avance les modèles des lignes suivantes.

 command | egrep -v "words|from|lines|you|dont|want" 

Cela fera un «OU inclusif», ce qui signifie qu’une ligne qui correspond à l’ un de ceux-ci sera exclue.

Je l’ai résolu avec deux grep séquentiels, en fait. Cela me semble beaucoup plus simple.

 grep -C "match" yourfile | grep -v -f - yourfile