Eu tenho o seguinte código que removerá linhas com o padrão banana
e 2 linhas depois dele:
sed '/banana/I,+2 d' file
Por enquanto, tudo bem! Mas preciso remover duas linhas antes banana
, mas não consigo obtê-lo com um "sinal de menos" ou o que for (semelhante ao que grep -v -B2 banana file
deve fazer, mas não faz):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
shell-script
text-processing
sed
awk
Teresa e Junior
fonte
fonte
awk '{l[m=NR]=$0}/banana/{for(i=NR-2;i<=NR;i++)delete l[i]}END{for(i=1;i<=m;i++)if(i in l)print l[i]}'
. Isso não é eficiente, portanto, é apenas uma dica, não uma solução.tac file | sed ... | tac
. : Psed '/banana/,+2d' file
que também funcionaráawk 'tolower($0)~/bandana/{print prev[!idx];print prev[idx]} {idx=!idx;prev[idx]=$0}' filein
como esse é um comentário e não uma resposta (já existem outras respostas), não entrarei em muitos detalhes, mas o ponto crucial é que você sempre tem o anteriores dois registros em prev [0] e prev [1], o "mais frescos" dependendo de qual iteração mas sempreprev[idx]
, então quando você imprimir, você imprime em!idx
seguidaidx
ordem. Independentemente disso, alterneidx
e insira o registro atualprev[idx]
.Respostas:
O Sed não volta atrás: uma vez processada uma linha, está pronta. Portanto, “encontre uma linha e imprima as N linhas anteriores” não funcionará como está, ao contrário de “encontre uma linha e imprima as próximas N linhas”, que são fáceis de enxertar.
Se o arquivo não for muito longo, já que você parece estar bem com as extensões GNU, você pode usar
tac
para reverter as linhas do arquivo.Outro ângulo de ataque é manter uma janela deslizante em uma ferramenta como o awk. Adaptação de Existe alguma alternativa aos comutadores -A -B -C do grep (para imprimir algumas linhas antes e depois)? (aviso: minimamente testado):
Uso:
/path/to/script -v pattern='banana' -v before=2
fonte
sed
também pode fazer janelas deslizantes, mas o script resultante geralmente é tão ilegível que é mais fácil usar apenasawk
.awk
script não está certo; como está, imprime linhas em branco e perde as últimas linhas. Isso parece corrigi-lo, mas pode não ser ideal ou correto:if (NR-before in h) { print...; delete...; }
... e naEND
seção:for (i in h) print h[i]
... Além disso, o script awk imprime a linha correspondente, mas atac/sec
versão não; mas a pergunta é um pouco ambígua nisso .. O script awk "original", para o qual você forneceu um link, funciona bem .. eu gosto ... não tenho certeza de como o 'mod' acima afeta a impressão depois linhas ...Isso é bem fácil com ex ou vim -e
A expressão diz: para cada linha que contém banana no intervalo da linha atual -2 à linha atual, exclua.
O legal é que o intervalo também pode conter pesquisas para trás e para a frente, por exemplo, isso excluirá todas as seções do arquivo começando com uma linha contendo maçã e terminando com uma linha contendo laranja e contendo uma linha com banana:
fonte
Usando a "janela deslizante" em
perl
:fonte
Você pode fazer isso de maneira bastante simples com
sed
:Não sei por que alguém diria o contrário, mas, para encontrar uma linha e imprimir as linhas anteriores,
sed
incorpora aP
primitiva integrada da rint, que grava apenas até o primeiro\n
caractere da linha de ewline no espaço do padrão. AD
primitiva elete complementar remove o mesmo segmento do espaço do padrão antes de reciclar recursivamente o script com o que resta. E, para finalizar , existe uma primitiva para anexar aN
linha de entrada ext ao espaço do padrão, após um\n
caractere de linha de linha inserido .Para que uma linha de
sed
seja tudo o que você precisa. Você apenas substitui o quematch
quer que seja o seu regexp e fica com o ouro. Essa deve ser uma solução muito rápida também.Observe também que ele contará corretamente um
match
imediatamente anterior a outromatch
como um acionador para silenciar a saída das duas linhas anteriores e também silenciar sua impressão:Para funcionar para um número arbitrário de linhas, tudo o que você precisa fazer é obter uma vantagem.
Tão:
... exclui as 5 linhas que precedem qualquer correspondência.
fonte
Usando
man 1 ed
:fonte