Como remover uma única linha entre duas linhas

Como remover uma única linha entre duas linhas

Eu tenho milhões de registros em um arquivo parecido com este

echo "NEW Cell"
grep "2553,24" out.2A25.20090308.64436.7.HDF.txt.text = 22.58   5.39  82.09 237
echo "NEW Cell"
grep "2555,20" out.2A25.20090308.64436.7.HDF.txt.text = 24.72   5.58  82.05 237
echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120
echo "NEW Cell"
grep "2560,24" out.2A25.20090308.64436.7.HDF.txt.text = 19.38   5.54  82.30 170
echo "NEW Cell"

Agora quero deletar a linha com "grep" com a condição de que seja a ÚNICA linha entre as linhas que contém "Nova Célula". Ou seja, se houver uma linha de grep entre a nova célula, essa linha deverá ser excluída.

Como fazer isso?

Minha saída deve ser semelhante a,

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

Responder1

AWKsolução:

awk 'NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }
     /NEW Cell/{ f=1; n=NR+2; r=$0; next }
     f && n-NR==1 && /^grep /{ gr=$0; next }1' file
  • /NEW Cell/{ f=1; n=NR+2; r=$0; next }- ao encontrar linha comNEW Cell

    • f=1= definir sinalizador ativof=1
    • n=NR+2- definir no número máximo das seguintes linhas a serem processadas (2 próximas linhas)
    • r=$0- capturando a linha
    • next- pular para o próximo registro
  • f && n-NR==1 && /^grep /- ao encontrar a 2ª linha (garantida por n-NR==1) que começa com grepa palavra-chave

    • gr=$0; next- capturar greplinha e pular para o próximo (terceiro) registro
  • NR==n{ if (/NEW Cell/) { f=0 } else print r ORS gr }- ao encontrar a 3ª linha crucial (garantida por NR==n)

    • if (/NEW Cell/) { f=0 }- se a terceira linha da seção processada contiver NEW Cell- redefina o processamento atual com f=0(todas as linhas capturadas anteriormente serão ignoradas)
    • else print r ORS gr- caso contrário, imprima todas as linhas capturadas anteriormente

A saída:

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

Responder2

Solução compacta com sed:

sed '/NEW Cell/!{H;d;};x;/\n.*\n/!d'

Se a linha não contiver NEW Cellexecute Hpara anexar a linha ao espaço de espera e dinterromper o processamento dessa linha.

Portanto, outros comandos são aplicados apenas às NEW Celllinhas: O xespaço padrão troca e o espaço de espera, portanto a linha está agora no espaço de espera e outras linhas podem ser anexadas, enquanto o espaço de padrão contém tudo anexado à última NEW Celllinha. Seu requisito é que haja mais de uma linha entre as NEW Celllinhas, portanto deve haver pelo menos duas novas linhas no espaço do padrão. Caso contrário, exclua-o sem saída: /\n.*\n/!d.

Responder3

Com rudimentar awk...

A versão 1 excluirá apenas grepas linhas que seguem a descrição do OP:

awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
     else { f=1; s=$0 } } ! /^echo/ { print; f=0 } \
     ! /^echo/ && ! /^grep/ { print }' inputfile

A versão 2 excluirá grepas linhas solo, bem como a linha anterior não-grep que segue o exemplo de saída do OP:

awk '/^grep/ { if (f) { if (length(s) > 0) { print s; s="" } print } \
    else { f=1; s=s "\n" $0 } } /^echo/ { s=$0; f=0 } \
    ! /^echo/ && ! /^grep/ { print }' inputfile

Forma legível da versão 2...

/^grep/ { 
   if (found) {  # found==true : already encountered first grep line
       if (length(save) > 0) {
          print save
          save=""
       }
       print
   } else {
       found=1
       save=save "\n" $0  # append the first grep line to saved preceding line
   }
}

/^echo/ { 
    save=$0  # save this line for possible later printing
    found=0
}

# print anything else
! /^echo/ && ! /^grep/ { print }

Este formato longo pode ser executado colocando o conteúdo em um arquivo (por exemplo awkfile, ) e awk -f awkfile inputfile.

Responder4

gawk '
/\n.+\n/{
    printf("%s%s", RS, $0);
}' RS='echo "NEW Cell"\n' input.txt

Explicação:

  1. RS='echo "NEW Cell"\n'- RSé o separador do registro de entrada, por padrão uma nova linha. Agora ele foi alterado para echo "NEW Cell"\n, assim, todas as ocorrências desta string serão removidas e todos os caracteres entre elas passarão a ser o item de registro.
  2. /\n.+\n/{- somente para registros que correspondam a este padrão - nova linha, um ou mais caracteres, nova linha. Então, ele corresponde apenas a registros multilinhas, o registro de linha única não corresponde, pois possui apenas um arquivo \n.
  3. printf("%s%s", RS, $0);- imprime o registro, precedido do RS( echo "NEW Cell"\n).

Saída

echo "NEW Cell"
grep "2557,20" out.2A25.20090308.64436.7.HDF.txt.text = 19.75   5.62  82.11 170
grep "2557,21" out.2A25.20090308.64436.7.HDF.txt.text = 24.34   5.58  82.13 120
grep "2558,22" out.2A25.20090308.64436.7.HDF.txt.text = 22.2   5.57  82.19 120
echo "NEW Cell"
grep "2560,22" out.2A25.20090308.64436.7.HDF.txt.text = 24.69   5.62  82.25 160
grep "2561,23" out.2A25.20090308.64436.7.HDF.txt.text = 24.74   5.60  82.30 120

informação relacionada