Estou tentando contar o número de linhas de saída que um determinado programa produz. O problema é que o programa leva muito tempo para ser executado e eu quero exibir a saída para o usuário. Existe uma maneira de contar o número de linhas do último comando emitido?
Eu poderia fazer program | wc -l, mas isso não mostraria a saída para o usuário. Pelo que sei, tenho que fazer program; program | wc -l – mas o programa leva pelo menos um minuto para ser executado, então não quero ter que fazer mais de uma vez, apenas para mostrar uma contagem de linha na parte inferior.
EDITAR:
- Existe uma maneira de mostrar a saída conforme ela acontece (linha por linha) e depois retornar uma contagem no final?
Comentários
Resposta
Você pode usar tee para dividir o fluxo de saída enviando uma cópia para wc e a outra cópia para STDOUT normalmente.
program | tee >(wc -l)
A >(cmd) é a sintaxe bash, que significa ru n cmd e substitua o bit >(cmd) pelo caminho para (um canal nomeado conectado a) STDIN desse programa.
Comentários
-
>(cmd)ékshsintaxe também reconhecida porzshebashe está usando apenas pipes nomeados em sistemas que não ' t tem/dev/fd/n. - @StephaneChazelas Sim, a maioria dos shells é compatível, mas ' não está em POSIX, para que ' não seja confiável para estar em todos os lugares.
- Sim, eu estava apenas apontando que a substituição do processo não era uma
bashinvenção como o texto em sua resposta poderia fazer alguém acreditar. - @TheLibbster Depende de como você define eficiente. Este método envolve a geração de 2 processos adicionais, onde
sedeawksão apenas um. Masteeewcsão extremamente pequenos (muito menores do quesedeawk). - @TheLibbster sim, de acordo com alguns testes simples que acabei de fazer, ' é duas vezes mais rápido como os métodos
sedeawk. (Iddd 100mb de/dev/urandompara um arquivo e, em seguida, executei esse arquivo em cada método várias vezes)
Resposta
Uma opção é usar awk, que pode fazer a contagem e imprimir em stdout.
program | awk "{ print } END { print NR }"
Em awk, NR é o número da linha atual. Você pode fazer o mesmo com perl:
program | perl -pe "END {print "$.\n"}"
Ou sed:
program | sed -n "p;$="
Comentários
- Existe uma maneira de mostrar a saída conforme ela acontece (linha por linha) e, em seguida, retornar uma contagem no final ?
Resposta
minha opção favorita:
program | grep "" -c
Comentários
- OP pode ter perguntado outra coisa, mas vim aqui procurando apenas obter uma contagem do número de linhas de saída e não ' não se preocupe em mostrar a saída real, e isso faz o trabalho. Obrigado!
Resposta
Você pode clonar stdout em stderr.
program | tee /dev/stderr | wc -l
Dessa forma, program” s stdout é canalizado para tee para ser escrito em stderr, que é impresso no console. tee também grava os dados canalizados para ele em seu stdout, que é canalizado para wc.
Resposta
Isso pode ser tarde. Mas gostaria apenas de responder à sua pergunta de acompanhamento sobre como capturar o número contado em uma variável.
Isso é o que você deseja YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l).
Aproveitamos tee para gerar dois fluxos aqui e direcione um para /dev/stderr, que apareceria em sua tela, e o outro para wc -l, que relataria o número de linhas.
Resposta
tail -f /var/log/squid/access.log | ( c=0; pl() { echo $c; c=0; }; trap pl SIGHUP; while read a; do (( c=c+1 )); done ) & ( trap "kill $! ; exit" SIGINT; trap "" SIGHUP; while true; do kill -HUP $! ; sleep 1; done)
STDOUT_WRITE_COUNT), ou registre-o em um arquivo / API, no final do programa. WDYT?