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)
éksh
sintaxe também reconhecida porzsh
ebash
e 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
bash
invençã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
sed
eawk
são apenas um. Mastee
ewc
são extremamente pequenos (muito menores do quesed
eawk
). - @TheLibbster sim, de acordo com alguns testes simples que acabei de fazer, ' é duas vezes mais rápido como os métodos
sed
eawk
. (Idd
d 100mb de/dev/urandom
para 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?