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
AWK
soluçã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
- definirn
o número máximo das seguintes linhas a serem processadas (2 próximas linhas)r=$0
- capturando a linhanext
- pular para o próximo registro
f && n-NR==1 && /^grep /
- ao encontrar a 2ª linha (garantida porn-NR==1
) que começa comgrep
a palavra-chavegr=$0; next
- capturargrep
linha 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 porNR==n
)if (/NEW Cell/) { f=0 }
- se a terceira linha da seção processada contiverNEW Cell
- redefina o processamento atual comf=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 Cell
execute H
para anexar a linha ao espaço de espera e d
interromper o processamento dessa linha.
Portanto, outros comandos são aplicados apenas às NEW Cell
linhas: O x
espaç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 Cell
linha. Seu requisito é que haja mais de uma linha entre as NEW Cell
linhas, 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 grep
as 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á grep
as 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:
RS='echo "NEW Cell"\n'
-RS
é o separador do registro de entrada, por padrão uma nova linha. Agora ele foi alterado paraecho "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./\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
.printf("%s%s", RS, $0);
- imprime o registro, precedido doRS
(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