Várias pesquisas do Grep

1

Eu desejo obter a última linha de um arquivo de log que corresponda a uma string de teste e a saída para outro arquivo de log.

Eu preciso testar várias seqüências de texto diferentes e, dependendo da saída enviada para um arquivo de log diferente.

Estou usando isso:

tail -f -n 1 input.log | grep string1 >>output1.log

Então eu quero repetir o teste assim:

tail -f -n 1 input.log | grep string2 >>output2.log
tail -f -n 1 input.log | grep string3 >>output3.log

Como posso conseguir isso em um único script bash eficiente?

    
por Colin Davis 04.02.2018 / 16:19

3 respostas

5

usando awk ao invés de grep:

awk '/string1/ { print >> "output1.log" ; fflush() }
     /string2/ { print >> "output2.log" ; fflush() }
     /string3/ { print >> "output3.log" ; fflush() }' input.log

Isso gera all linhas correspondentes aos seus respectivos arquivos output.log. Isso porque não consigo entender seus requisitos tail -f e tail -n 1 conflitantes. Se você realmente quiser que ele comece a seguir input.log da última linha atual, canalize tail -f -n 1 no script awk e livre-se do input.log no final da linha. por exemplo,

tail -f -n 1 input.log | awk '...same awk script as above...'

Você também pode fazer isso com tee e grep e substituição de processo  (mas será visivelmente mais lento):

tee >(grep --line-buffered string1 >> output1.log) \
    >(grep --line-buffered string2 >> output2.log) \
    >(grep --line-buffered string3 >> output3.log) < input.log

ou

tail -f -n 1 input.log | tee .....

OBSERVAÇÃO: A fflush() na solução awk e a opção --line-buffered na solução tee são necessárias apenas se você estiver canalizando a saída de tail -f ( ou algum outro processo interminável) em awk ou tee .

Sem eles, os arquivos de saída só serão gravados quando os buffers de saída (de awk ou grep) estiverem cheios - e se o trabalho for abortado enquanto houver saída não escrita nos buffers (por exemplo, pressionando Ctrl-C) a saída ainda nos buffers será perdida.

Com eles, ambas as soluções rodam muito mais devagar (porque elas liberam a saída a cada gravação) - mas é improvável que seja significativo, exceto com arquivos de entrada muito grandes.

BTW, isso não é um problema quando a entrada termina - nesse caso, tanto o awk quanto o grep liberam automaticamente seus buffers de saída antes de sair.

Outra alternativa seria executar o pipe em awk (ou tee ) em um sub-shell que aprisionou e ignorou o sinal de interrupção do Ctrl-C. por exemplo,

tail -f input.log | ( 
  trap '' INT
  awk '/string1/ { print >> "output1.log" }
       /string2/ { print >> "output2.log" }
       /string3/ { print >> "output3.log" }'
  )

O tail -f é afetado (morto) pressionando Ctrl-C, mas o sub-shell executando awk o ignora. awk libera seus buffers de saída e sai quando o tail é eliminado porque sua entrada foi concluída.

Veja Armadilha Ctrl-C no script do awk para outro exemplo / explicação.

Se você não quiser que ele siga o arquivo de log, não use a opção tail -f .

Use apenas tail -n 1 | ..... ou veja a resposta de Guy, que imprime a última correspondência das três strings em seus respectivos arquivos de saída.

    
por 04.02.2018 / 16:31
1

Editando a solução do cas, para se concentrar na sua linha.

I wish to get the last line of a log file that matches a test string and output to another log file.

awk '
    # every time theres a match, save that line into a variable
    /string1/ { str1 = $0 }
    /string2/ { str2 = $0 }
    /string3/ { str3 = $0 }
    END {
      # and only print to file after reading the whole log.
      print str1 >> "output1.log"
      print str2 >> "output2.log"
      print str3 >> "output3.log" 
}' input.log
    
por 04.02.2018 / 16:44
0

arquivo de entrada

praveen
ajay
abhi
praveen
ajay
abhi
kiran
tomato

Nosso requisito é pesquisar na sequência de texto diferente a gravação da saída em um arquivo de texto diferente

Eu usei o comando loop e sed para o mesmo

Eu tentei pesquisar por conteúdo praveen, ajay, abhi e salva a saída em contentsearch.txt

Script

for i in praveen ajay abhi; do sed -n "/$i/p" input.txt > $i.txt; done

Abaixo, a saída

praveen.txt  will contains line where praveen is present
ajay.txt will contains line where ajay is present
abhi.txt will contains where abhi is present

=============================================== ===============================

Se você quiser procurar pela última linha do arquivo de log que corresponde à string de teste e a saída para outro arquivo, use o comando abaixo

sed -n '/Contentsearch/p' input.txt | tail -1 > output.txt
    
por 04.02.2018 / 16:46