Como imprimir uma linha se essa linha ou a próxima linha não contiver uma sequência específica


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

Saída desejada:

    8B0F
    8AC0
    8AE4
    8AE5

Quero imprimir uma linha se essa linha ou a próxima linha não contiver 'remover'. Estou usando o solaris 5.10, KSH.


@don_crissti Obrigado, posso marcar esta pergunta como respondida se você postar sua resposta em vez de comentar.
ayrton_senna

Respostas:


14

Com sed:

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

Isso puxa a Nlinha ext para o espaço do padrão (se não estiver !na $linha t) e verifica se o espaço do padrão corresponde remove. Se não existir (significa que nenhuma das duas linhas no espaço do padrão contém a sequência remove), ela Pcria o primeiro \ncaractere de linha de linha (ou seja, imprime a primeira linha). Em seguida, Delimina o primeiro \ncaractere de linha de linha e reinicia o ciclo. Dessa forma, nunca há mais de duas linhas no espaço do padrão.


É provavelmente mais fácil de entender o N, P, Dciclo se você adicionar lantes e após a Nolhar para o espaço padrão:

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

portanto, usando apenas as últimas seis linhas do seu exemplo:

    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

o último comando gera:

    8AC3 $
    8AC3 \ n remover $
    remove $
    remover \ n 8AE4 $
    8AE4 $
    8AE4 \ n 8AE5 $
    8AE4
    8AE5 $
    8AE5 \ n 8AE6 $
    8AE5
    8AE6 $
    8AE6 \ n remover $
    remove $
    remove $

Aqui está uma breve explicação:

cmd saída 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)

5
awk '
    !/remove/ && NR > 1 && prev !~ /remove/ {print prev} 
    {prev = $0} 
    END {if (!/remove/) print}
' Input.txt 

2
gawk 'BEGIN{ RS="remove\n"; ORS="" }
      RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file

O método acima não lê Registros linha por linha , mas lê Registros com várias linhas de um Separador de Registros (RS) para o próximo (ou final de arquivo) - RSsendo a própria linha "remover" (incluindo sua à direita `\ n).

O !RTteste é necessário para quando a última linha não for uma RSlinha.
RT, um gawk-ism , é o texto real dos registros atuais RS.
gensubtambém é um gawk-ism .

Se você precisar verificar se há uma linha de marcador que corresponda a "remover" em qualquer lugar da linha, versus uma linha que seja igual a "remover", basta alterar o Separador de registros para:

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

Resultado:

8B0F
8AC0
8AE4
8AE5
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.