Contare il numero di righe di output dal programma precedente

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

  • Che ne dici: fai in modo che il programma tenga traccia del proprio output e legga semplicemente quel valore dalla variabile (es. STDOUT_WRITE_COUNT) o registralo in un file / API alla fine del programma. WDYT?

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 da zsh e bash 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 e awk sono solo uno. Ma tee e wc sono entrambi estremamente piccoli (molto più piccoli di sed e awk).
  • @TheLibbster sì, secondo alcuni semplici test che ho appena fatto, ' in realtà è circa il doppio più veloce come entrambi i metodi sed e awk. (Ho dd 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) 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *