Comment imprimer une ligne si cette ligne ou la ligne suivante ne contient pas de chaîne particulière

8

Input.txt:

    8B0C
    remove
    8B0D
    remove
    8B0E
    remove
    8B0F
    8B10
    remove
    8B14
    remove
    8B15
    remove
    8B16
    remove
    8B17
    remove
    8AC0
    8AC1
    remove
    8AC2
    remove
    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

Sortie désirée:

    8B0F
    8AC0
    8AE4
    8AE5

Je veux imprimer une ligne si cette ligne ou la ligne suivante ne contient pas «supprimer». J'utilise Solaris 5.10, KSH.

ayrton_senna
la source
@don_crissti Merci, je peux marquer cette question comme répondue si vous postez votre réponse au lieu de commenter.
ayrton_senna

Réponses:

14

Avec sed:

sed '$!N;/remove/!P;D' infile

Cela tire la Nligne ext dans l'espace modèle (si ce n'est pas !sur la $ligne t) et vérifie si l'espace modèle correspond remove. Si ce n'est pas le cas (cela signifie qu'aucune des deux lignes de l'espace de motif ne contient la chaîne remove), elle Ps'imprime jusqu'au premier \ncaractère ewline (c'est-à-dire qu'elle imprime la première ligne). Ensuite, il se Dtermine jusqu'au premier \ncaractère ewline et redémarre le cycle. De cette façon, il n'y a jamais plus de deux lignes dans l'espace de motif.


Il est probablement plus facile de comprendre le N, P, le Dcycle si vous ajoutez lavant et après la Nregarder l'espace de travail :

sed 'l;$!N;l;/remove/!P;D' infile

donc, en utilisant uniquement les six dernières lignes de votre exemple:

    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

la dernière commande sort:

    8AC3 $
    8AC3 \ n supprimer $
    supprimer $
    supprimer \ n 8AE4 $
    8AE4 $
    8AE4 \ n 8AE5 $
    8AE4
    8AE5 $
    8AE5 \ n 8AE6 $
    8AE5
    8AE6 $
    8AE6 \ n supprimer $
    supprimer $
    supprimer $

Voici une courte explication:

sortie cmd cmd
l     8AC3$                  N # read in the next line
l     8AC3\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                N # read in the next line
l     remove\n    8AE4$      D # delete up to \n (pattern space matches so no P)
l     8AE4$                  N # read in the next line
l     8AE4\n    8AE5$        # pattern space doesn't match so print up to \n
P     8AE4                   D # delete up to \n
l     8AE5$                  N # read in the next line
l     8AE5\n    8AE6$        # pattern space doesn't match so print up to \n
P     8AE5                   D # delete up to \n 
l     8AE6$                  N # read in the next line
l     8AE6\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                # last line so no N 
l     remove$                D # delete (pattern space matches so no P)
don_crissti
la source
5
awk '
    !/remove/ && NR > 1 && prev !~ /remove/ {print prev} 
    {prev = $0} 
    END {if (!/remove/) print}
' Input.txt 
glenn jackman
la source
2
gawk 'BEGIN{ RS="remove\n"; ORS="" }
      RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file

La méthode ci-dessus ne lit pas les enregistrements ligne par ligne , mais lit plutôt les enregistrements multilignes d'un séparateur d'enregistrements (RS) au suivant (ou à la fin du fichier) - RSétant la ligne "supprimer" elle-même (y compris son "\ n).

Le !RTtest est nécessaire lorsque la dernière ligne n'est pas une RSligne.
RT, un gawk-ism , est le texte réel de l'enregistrement en cours RS.
gensubest aussi un gawk-isme .

Si vous devez rechercher une ligne de marqueur qui correspond à "supprimer" n'importe où dans la ligne, par rapport à une ligne qui équivaut à "supprimer", changez simplement le séparateur d'enregistrement en:

`RS="[^\n]*remove[^\n]*\n"`  

Production:

8B0F
8AC0
8AE4
8AE5
Peter.O
la source