J'essaie de supprimer toutes les instances d'une correspondance de modèle d'un fichier si elle correspond à un modèle. S'il y a une correspondance, la ligne (complète) avec le modèle de correspondance et la ligne suivante sont supprimées.
La ligne suivante apparaît toujours après la ligne avec la correspondance de modèle, mais en plus elle apparaît dans d'autres zones du fichier.
J'utilise grep et il supprime toutes les occurrences de la ligne suivante dans le fichier, comme prévu.
Existe-t-il un moyen de supprimer la ligne suivante si et seulement si c'est après la ligne avec la correspondance de motif?
Vous pouvez utiliser sed
avec les commandes N
et d
et une {}
block :
sed -e '/pattern here/ { N; d; }'
Pour chaque ligne correspondant à pattern here
, le code dans le {}
s'exécute. N
prend également la ligne suivante dans l'espace de motif, puis d
supprime le tout avant de passer à la ligne suivante. Cela fonctionne dans n'importe quel sed
compatible POSIX.
Une solution awk:
awk '/pattern/ { matched=1; next }
1 == matched { matched = 0; next }
{ print }' input-file
La ligne 1 recherche les lignes correspondant au motif, définit un indicateur et saute la ligne. La ligne 2 saute une ligne lorsque l'indicateur est défini, mais réinitialise l'indicateur. La ligne 3 imprime les lignes qui n'ont pas été ignorées par l'une des deux autres lignes.
Vous pouvez taper ceci sur une seule ligne si vous le souhaitez:
awk '/pattern/{matched=1;next} 1==matched{matched=0;next} {print}' input-file
Voici une variante qui vous permet de contrôler le nombre de lignes à ignorer:
awk '/pattern/{skip=3;next} skip>0{--skip;next} {print}' input-file
Définissez skip
sur le nombre de lignes à ignorer (en plus de la ligne correspondante).
La plupart des sed
n'impriment pas la dernière ligne si vous N
sur $
. Mais GNU sed
le fera. Donc, si le motif que vous voulez supprimer est sur la dernière ligne et vous N
il s’imprimera. Il est parfois préférable de tampon plein - comme dans, contenant toujours 2 lignes sauf sur les lignes que vous ne voulez pas imprimer. Vous pourriez le faire comme:
seq 10 | sed -n 'x;/7/!g;//!p'
C'est un exemple avec seq
en entrée. Sur chaque ligne, il échange l'espace de maintien et l'espace de motif. Si la dernière ligne suspendue ne correspond pas à un 7
(dans ce cas) il remplacera l'espace d'attente par la ligne courante. Il vérifie ensuite à nouveau que la ligne qu'il vient de tracer - la ligne actuelle - ne correspond pas non plus au 7
, sinon il ne l'imprimera pas. Ainsi, sur chaque ligne, il vérifie la ligne précédente et la ligne actuelle.
1
2
3
4
5
6
9
10
Et si votre motif tombe sur la dernière ligne:
seq 10 | sed -n 'x;/10/!g;//!p'
1
2
3
4
5
6
7
8
9
Un autre exemple, pour espérer démontrer plus clairement ce qu'il imprimera et n'imprimera pas:
sed -n 'x;/match/!g;//!p
' <<\DATA
match
match
1not
2not
3not
4not
5not
match
6not
match
DATA
2not
3not
4not
5not
cat sample
Pattern line
next after pattern line
this is another
random line
next after pattern line
has occured without.
now we have
another
Pattern line
next after pattern line
let us see the output.
Maintenant, j'émets la commande ci-dessous.
sed -e '/Pattern \line/,+1d' sample
C'est la sortie que j'obtiens.
this is another
random line
next after pattern line
has occured without.
now we have
another
let us see the output.
suivant après la ligne de motif n'est pas supprimé lorsqu'il apparaît comme une ligne distincte non à côté de modèle.
Selon les commentaires de Michael, la syntaxe ci-dessus est GNU. Vous pouvez essayer quelque chose comme,
sed -e '/Pattern \line/{N;d}' sample
Que diriez-vous
sed '/pattern/ {$!N;d;}' file