Exclua a linha correspondente e várias outras de um arquivo

4

Eu tenho um arquivo de texto chamado file_a.txt. Meu primeiro comando é

grep -A 12 ".production =" file_a.txt

A saída é de poucos blocos. Cada bloco de string contém 13 linhas

Eu quero excluir especificamente todo o bloco de strings que recebi com o comando grep do arquivo original file_a.txt. Eu não quero enviar a saída do grep para um novo arquivo. Também não quero usar grep -v porque não funciona no meu caso.

Eu tentei algo assim, mas nada está funcionando:

cut < grep -A 12 ".production =" file_a.txt

sed -i '/'grep -A 12 ".production ="'/d' file_a.txt
    
por Clayton 09.10.2012 / 11:55

4 respostas

3

caminho sed do GNU

Em GNU sed (se você estiver usando alguma distribuição Linux, deve ser a implementação sed padrão), você pode usar algo assim:

sed '/.production =/,+12d' inputfile.txt

Como funciona:

  1. Ele verifica o arquivo de entrada linha por linha (é assim que o sed funciona) e verifica se o comando deve ser usado.
  2. Nosso comando é d (o último caractere), o que significa excluir a linha.
  3. Mas este comando só será executado se a linha atual corresponder ao nosso intervalo.
  4. O intervalo é especificado por dois argumentos (início e fim do intervalo, inclusive) delimitados por , character. A primeira é uma expressão regular /.production =/ que corresponde a cada linha que contém essa expressão. O segundo argumento é +12d , o que significa 12 lines from start range .
  5. Assim, nosso alcance corresponde a cada linha que corresponde à expressão e às próximas 12 linhas e as exclui.
  6. Todas as outras linhas são impressas na saída (padrão sed behaviour ).

Caminho portátil e feio

Este deve funcionar em outra implementação de sed , mas envolve muito mais digitação e não é tão robusto:

sed '/.production =/{N;N;N;N;N;N;N;N;N;N;N;N;d}' somefile.txt

Como funciona:

  1. Ele verifica o arquivo de entrada linha por linha (é assim que o sed funciona) e verifica se o comando deve ser usado.
  2. Verifica se a linha corresponde ao padrão /.production =/ . Em caso afirmativo, ele executa todos os comandos em {} chaves.
  3. Corremos N comamnd 12 vezes. O comando N lê a próxima linha e a anexa ao buffer atual. Então, depois de executá-lo 12 vezes, temos 13 linhas concatenadas no buffer atual (primeira linha + 12 leitura por N de comandos).
  4. Agora executamos o comando d , que exclui essas 13 linhas concatenadas.
  5. sed continua até encontrar outro padrão e novamente exclui 13 linhas. Todas as outras linhas são impressas (padrão sed behavior).
por 09.10.2012 / 12:12
0

Você pode recuperar o número da linha em que deseja iniciar a filtragem e filtrá-lo com o AWK.

Em AWR, NR significa o número do registro, por padrão, é o fim da linha (\ n).

START_LINE=$(cat file_a.txt | grep -n .production | cut -f1 -d:)
cat file_a.txt | awk '{ if(NR < '$START_LINE' || NR > '$START_LINE' + 12) print $0; }'
    
por 09.10.2012 / 12:13
0

Quando o grep e o sed não estão cortando, procure o awk. O awk pode emular a maioria dos utilitários de texto facilmente ( sort sendo a principal exceção) e pode combiná-los de maneiras mais flexíveis do que o piping.

awk '
    /.production =/ {skip_lines = 13}
    skip_lines {--skip_lines}
    !skip_lines {print}
' file_a.txt >file_a.txt.new &&
mv file_a.txt.new file_a.txt
    
por 10.10.2012 / 01:36
0

Você pode usar o Vim no modo Ex:

ex -sc '/.production =/d13|x' file_a.txt
  1. // move para a linha correspondente

  2. 13 selecione 13 linhas

  3. d delete

  4. x salvar e fechar

por 17.04.2016 / 05:20