Contare il numero di righe di output dal programma precedente


32

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 voglio visualizzare l'output per l'utente. C'è un modo per contare il numero di righe emesse dall'ultimo comando?

Potrei farlo program | wc -lma ciò non mostrerebbe l'output all'utente. Quindi, per quanto ne so, devo farlo program; program | wc -l, ma l'esecuzione del programma richiede almeno un minuto, quindi non voglio farlo più di una volta solo per mostrare un conteggio delle righe in fondo.

MODIFICARE:

  • Esiste un modo per mostrare l'output in tempo reale (riga per riga) e quindi restituire un conteggio alla fine?

Che ne dite: fate in modo che il programma tenga traccia del proprio output e legga semplicemente quel valore dalla variabile (ad es. STDOUT_WRITE_COUNT), O registratelo in un file / API, alla fine del programma. WDYT?
Mecampbellsoup,

Risposte:


43

È possibile utilizzare teeper dividere il flusso di output inviando una copia wce l'altra copia a STDOUT come al solito.

program | tee >(wc -l)

È la >(cmd)sintassi bash che significa eseguire cmde sostituire il >(cmd)bit con il percorso a (una pipe denominata collegata) al programma STDIN.


2
>(cmd)la kshsintassi è anche riconosciuta da zshe bashe sta usando solo named pipe su sistemi che non hanno /dev/fd/n.
Stéphane Chazelas,

@StephaneChazelas Sì, la maggior parte delle shell lo supporta, ma non è in POSIX, quindi non si può fare affidamento su di essere ovunque.
Patrick,

Sì, stavo solo sottolineando che la sostituzione del processo non era bashun'invenzione in quanto il testo nella tua risposta poteva far credere.
Stéphane Chazelas,

1
@TheLibbster Dipende da come definisci efficiente. Questo metodo prevede la generazione di 2 processi aggiuntivi, dove as sede awksono solo uno. Ma teee wcsono entrambi estremamente piccoli (molto più piccoli di sede awk).
Patrick,

1
@TheLibbster sì, secondo alcuni semplici test ho appena fatto, in realtà è circa due volte più veloce sia le sede awkmetodi. (Ho dd100 mb di /dev/urandomun file e poi ho eseguito quel file più volte con ciascun metodo)
Patrick

10

Un'opzione è 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;$='

Esiste un modo per mostrare l'output in tempo reale (riga per riga) e quindi restituire un conteggio alla fine?
Libbux,

6

Puoi clonare stdout su stderr.

program | tee /dev/stderr | wc -l

In questo modo, lo programstdout viene reindirizzato per teeessere scritto su stderr, che è stampato sulla console. teescrive anche i dati inviati ad esso sul suo stdout, a cui viene eseguito il piping wc.


3

la mia opzione preferita:

program | grep "" -c

1
L'OP potrebbe aver chiesto qualcos'altro, ma sono venuto qui cercando solo un conteggio del numero di righe in uscita e non mi importava di mostrare l'output effettivo, e questo fa il lavoro. Grazie!
Nikhil VJ,

0
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)

0

Questo potrebbe essere in ritardo. Ma vorrei solo rispondere alla tua domanda di follow-up su come catturare il numero contato in una variabile.

Questo è ciò che si desidera YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l).

Approfittiamo della teegenerazione di due flussi qui e di indirizzarne uno a /dev/stderr, che apparirebbe sullo schermo dell'utente, e l'altro a wc -l, che segnalerebbe il numero di linee.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.