Como encontrar a última ocorrência do padrão e imprimir todas as linhas após a última ocorrência [duplicado]

3

Eu tenho um arquivo que contém várias ocorrências do padrão "====" . Esses padrões são seguidos por textos. Gostaria de pesquisar a última ocorrência do padrão "====" e imprimir todas as linhas após o padrão. Alguma idéia de como fazer isso no bash? Combinação de grep , awk , sed ou tail , etc.?

Arquivo de amostra:

====

First run of script

End of first Script

====

2nd run of script

End of 2nd script

====

3rd run of script

End of 3rd script

A saída do comando deve se parecer abaixo.

3rd run of script

End of 3rd script
    
por user612223 09.09.2018 / 05:51

5 respostas

4

Com base em SO duplicate :

$ sed -n '/====/h;//!H;$!d;x;//p' sample.txt 
====

3rd run of script

End of 3rd script

Output of the command should look like below.

3rd run of script

End of 3rd script

Eu comecei a escrever uma explicação, mas na verdade não entendi alguns dos comandos, então vou me referir a info sed .

    
por 09.09.2018 / 06:48
4

Método de ferramentas de software, mais eficiente para arquivos grandes, pois só lê o final do arquivo e pára quando encontra a última correspondência:

tac sample.txt | grep -F -m1 -B 999999 '====' | head -n -1 | tac

Observação: aumente ou reduza 999999 conforme necessário, apenas para que seja mais longo do que qualquer correspondência possível. Veja também * Resposta de Glenn Jackman com variantes para awk e sed que evitam a necessidade de 99999 . Para sistemas com recursos baixos, o método grep é o mais eficiente das três variantes.

    
por 09.09.2018 / 12:59
1

salve o texto em file.txt e execute este comando:

awk 'p; /====/ $p' file.txt | tail -3

saída:

3rd run of script

End of 3rd script
    
por 09.09.2018 / 13:02
1

O mesmo conceito da resposta da agc, mas não exige que você adivinhe quantas linhas pode haver:

com o GNU sed

tac file | sed '/====/Q' | tac

ou awk

tac file | awk '/====/ {exit} 1' | tac

A ideia do double tac é inverter a questão: Como imprimir todas as linhas precedentes as primeiro     

por 09.09.2018 / 14:31
0

Em awk , algo assim:

awk '/====/ { t = ""; next } { t = t $0 "\n"; } END { printf "%s", t; }' < sample.txt

Armazena as linhas de entrada em t e limpa t quando vê ==== . O que já está lá é impresso no final.

Note que

  • O ==== não precisa estar em uma linha própria (estritamente falando, você não disse que deveria ser). Se você quiser apenas reconhecê-lo quando for a única coisa em uma linha, use /^====$/ .
  • Isso imprime toda a entrada se ==== não for visto. Verificando se há pelo menos um precisa de uma condição extra, veja abaixo.
  • Sua saída de amostra está sem a primeira linha vazia após o ==== , mas isso pode ser apenas a formatação da postagem. Se você quiser removê-lo, adicione um canal a sed 1d .

Outra versão que só começa a armazenar a entrada depois que o separador ==== é visto, produzindo efetivamente uma saída vazia se a entrada não contiver o separador:

awk '/====/ { any = 1; t = ""; next } any { t = t $0 "\n"; } END { printf "%s", t; }' < sample.txt
    
por 09.09.2018 / 14:11