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.