web-dev-qa-db-fra.com

Supprimer la ligne avec la correspondance de motif et la ligne suivante

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?

23
kenuse

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.

25
Michael Homer

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).

5
Kenster

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

PRODUCTION

2not
3not
4not
5not
5
mikeserv
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
4
Ramesh

Que diriez-vous

sed '/pattern/ {$!N;d;}' file
4
steeldriver