Jutilise ceci
cat foo.txt | sed "/bar/d"
pour supprimer les lignes contenant la chaîne bar
dans le fichier.
Je voudrais cependant supprimer ces lignes et la ligne directement après . De préférence dans sed
, awk
ou dans un autre outil disponible dans MinGW32.
Cest une sorte dinverse de ce que je peux obtenir dans grep
avec -A
et -B
pour imprimer également les lignes correspondantes sous forme de lignes avant / après la ligne correspondante.
Y a-t-il un moyen simple dy parvenir?
Commentaires
- Juste pour information: Je ‘ m analyse les journaux dans lesquels les entrées sont à deux lignes. Je veux donc trouver une entrée correspondant au modèle et la supprimer ainsi que la ligne suivante. Par conséquent, je nai ‘ pas besoin de gérer des lignes de correspondance consécutives, mais merci quand même pour lexhaustivité de vos réponses!
Réponse
Si vous avez GNU sed (donc Linux ou Cygwin non embarqué):
sed "/bar/,+1 d"
Si vous avoir bar
sur deux lignes consécutives, cela supprimera la deuxième ligne sans lanalyser. Par exemple, si vous avez un fichier de 3 lignes bar
/ bar
/ foo
, la ligne foo
restera.
Commentaires
- +1 pour la longueur 🙂 Dans mon cas exemple Je nai pas ‘ Jai des
bar
consécutifs, donc celui-ci est très facile à retenir. -
sed '/bar/d'
si vous voulez simplement » Supprimer la ligne contenant une certaine chaîne » et pas le suivant. - Si je veux supprimer toutes les lignes après les maths, alors?
- @Pandya Cela ‘ est différent. Vous pouvez utiliser par ex.
sed '/math/q'
- @ A.K. Si vous souhaitez simplement supprimer la ligne correspondante, ‘ est encore plus simple:
sed '/bar/d'
Réponse
Si bar
peut apparaître sur des lignes consécutives, vous pouvez faire:
awk "/bar/{n=2}; n {n--; next}; 1" < infile > outfile
qui peut être adapté pour supprimer plus de 2 lignes en changeant les 2 ci-dessus avec le nombre de lignes à supprimer, y compris celle correspondante.
Sinon, il « est facile à faire dans sed
avec la @MichaelRollins » solution ou:
sed "/bar/,/^/d" < infile > outfile
Commentaires
- Lautre avantage de la solution AWK est que je peux remplacer
/bar/
par/bar|baz|whatever/
. Danssed
cette syntaxe ne semble pas ‘ fonctionner. - @ jakub.g, jai GNU sed ( v4.4 maintenant). Pas sûr des autres. Ce que je sais, cest quil utilise la syntaxe dexpression régulière » basic » par défaut, cest pourquoi votre exemple na pas ‘ t travailler. Pour obtenir ce que vous voulez, vous pouvez soit placer une barre oblique inverse devant chaque ligne verticale, soit demander à
sed
dutiliser » extended » expressions régulières. Plus dinformations ici: gnu.org/software/sed/manual/html_node/… . Veuillez noter que cela sapplique également àgrep
. Voici ‘ mon propre exemple de travail:echo $'0a\n1b\n2c' | sed '/0a\|1b/d'
.
Réponse
Je ne parle pas couramment sed, mais cest facile de le faire dans awk:
awk "/bar/{getline;next} 1" foo.txt
Le awk script lit: pour une ligne contenant bar, récupérez la ligne suivante (getline), puis ignorez tout traitement ultérieur (suivant). Le motif 1 à la fin imprime les lignes restantes.
Mise à jour
Comme indiqué dans le commentaire, la solution ci-dessus ne fonctionnait pas avec bar
. Voici une solution révisée, qui en tient compte:
awk "/bar/ {while (/bar/ && getline>0) ; next} 1" foo.txt
Nous continuons maintenant à lire pour sauter toutes les / bar / lignes.
Commentaires
- Pour répliquer
grep -A
100%, vous devez également gérer nimporte quel nombre de lignes correctement (en supprimant le bloc entier et 1 ligne après).
Réponse
Pour ce faire, vous souhaiterez utiliser les capacités de script de sed.
$ sed -e "/bar/ { $!N d }" sample1.txt
Exemple de données:
$ cat sample1.txt foo bar biz baz buz
La commande « N » ajoute la ligne dentrée suivante dans lespace de motif. Ceci combiné avec la ligne de la correspondance de motif (/ bar /) sera les lignes que vous souhaitez supprimer. Vous pouvez alors supprimer normalement avec la commande « d ».
Commentaires
- Comment taper une nouvelle ligne dans la console? Ou est-ce uniquement un script?
- @ jakub.g: avec GNU sed:
sed -e '/bar/{N;d}' sample1.txt
Réponse
Si une ligne immédiatement après une correspondance doit être supprimée, alors votre programme sed
devra considérer des correspondances consécutives. En dautres termes, si vous supprimez une ligne après une correspondance qui correspond également, vous devriez probablement supprimer la ligne qui suit également.
Elle est implémentée assez simplement – mais vous devez regarder un peu en arrière .
printf %s\\n 0 match 2 match match \ 5 6 match match match \ 10 11 12 match 14 15 | sed -ne"x;/match/!{g;//!p;}"
0 6 11 12 15
Cela fonctionne en permutant les espaces dattente et de motif pour chaque ligne lue – de sorte que la dernière ligne puisse être comparée au courant à chaque fois. Ainsi, lorsque sed
lit une ligne, il échange le contenu de ses tampons – et la ligne précédente est alors le contenu de son tampon dédition, tandis que la ligne courante est mise en espace dattente.
Donc sed
vérifie la ligne précédente pour une correspondance avec match
, et si sa !
introuvable les deux expressions de la {
function }
sont exécutées. sed
g
et lespace de maintien en écrasant lespace de motif – ce qui signifie que la ligne actuelle est alors à la fois dans les espaces de maintien et de motif – puis il //
le vérifiera pour une correspondance avec sa dernière expression régulière compilée – match
– et si il nest pas match
il est p
imprimé.
Cela signifie quune ligne nest imprimée que si elle ne le fait pas match
et la ligne immédiatement précédente ne le fait pas match
. Il évite également tout échange inutile pour les séquences de match
es.
Si vous vouliez une version qui pourrait supprimer un nombre arbitraire de lignes survenant après un match
il faudrait un peu plus de travail:
printf %s\\n 1 2 3 4 match \ match match 8 \ 9 10 11 12 13 \ 14 match match \ 17 18 19 20 21 | sed -net -e"/match/{h;n;//h;//!H;G;s/\n/&/5;D;}" -ep
. .. remplacer le 5 par le nombre de lignes (y compris la ligne correspondante) que vous souhaitez supprimer …
1 2 3 4 12 13 14 21