Sto cercando di contare il numero di righe di output prodotte da un determinato programma. Il problema è che il programma richiede molto tempo per essere eseguito e desidero visualizzare loutput per lutente. Cè un modo per contare il numero di righe emesse dallultimo comando?
Potrei fare program | wc -l
ma questo non mostrerebbe loutput allutente. Per quanto ne so, devo fare program; program | wc -l
– ma il programma impiega almeno un minuto per essere eseguito, quindi non voglio doverlo fare più di una volta per mostrare un conteggio delle righe in fondo.
EDIT:
- Esiste un modo per mostrare loutput mentre accade (riga per riga) e poi restituire un conteggio alla fine?
Commenti
Risposta
Puoi utilizzare tee
per dividere il flusso di output inviando una copia a wc
e laltra copia in STDOUT come al solito.
program | tee >(wc -l)
>(cmd)
è la sintassi bash che significa ru n cmd
e sostituire il bit >(cmd)
con il percorso di (una pipe denominata collegata a) STDIN di quel programma.
Commenti
-
>(cmd)
èksh
sintassi riconosciuta anche dazsh
ebash
e utilizza solo named pipe su sistemi che non ' t avere/dev/fd/n
. - @StephaneChazelas Sì, la maggior parte delle shell lo supporta, ma ' non è in POSIX, quindi ' non ci si può fidare per essere ovunque.
- Sì, stavo solo facendo notare che la sostituzione del processo non era un
bash
invenzione come la formulazione nella tua risposta potrebbe far credere. - @TheLibbster Dipende da come definisci efficiente. Questo metodo implica la generazione di 2 processi aggiuntivi, dove
sed
eawk
sono solo uno. Matee
ewc
sono entrambi estremamente piccoli (molto più piccoli dised
eawk
). - @TheLibbster sì, secondo alcuni semplici test che ho appena fatto, ' in realtà è circa il doppio più veloce come entrambi i metodi
sed
eawk
. (Hodd
d 100 MB di/dev/urandom
in un file e poi ho eseguito il file attraverso ciascun metodo più volte)
Risposta
Unopzione è usare awk, che può eseguire il conteggio e stampare su stdout.
program | awk "{ print } END { print NR }"
In awk
, NR è il numero di riga corrente. Puoi ottenere lo stesso risultato con perl:
program | perl -pe "END {print "$.\n"}"
Oppure sed
:
program | sed -n "p;$="
Commenti
- Cè un modo per mostrare loutput mentre accade (riga per riga) e poi restituire un conteggio alla fine ?
Rispondi
la mia opzione preferita:
program | grep "" -c
Commenti
- OP potrebbe aver chiesto qualcosaltro, ma sono venuto qui cercando solo di ottenere un conteggio del numero di righe in uscita e non ' t interessa mostrare loutput effettivo, e questo fa il lavoro. Grazie!
Risposta
Puoi clonare stdout su stderr.
program | tee /dev/stderr | wc -l
In questo modo, program
” s stdout viene reindirizzato a tee
per essere scritto in stderr, che è stampato sulla console. tee
scrive anche i dati inviati tramite pipe al suo stdout, che viene reindirizzato a wc
.
Risposta
Potrebbe essere tardi. Ma vorrei solo rispondere alla tua domanda di follow-up su come catturare il numero contato in una variabile.
Questo è ciò che desideri YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l)
.
Approfittiamo del fatto che tee
generi due stream qui e indirizzarne uno a /dev/stderr
, che verrà visualizzato sullo schermo, e laltro a wc -l
, che riporterà il numero di righe.
Risposta
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
) o registralo in un file / API alla fine del programma. WDYT?