Räkna antalet utmatningsrader från föregående program

Jag försöker räkna antalet utmatningsrader som ett visst program producerar. Problemet är att programmet tar lång tid att köra, och jag vill visa utdata för användaren. Finns det ett sätt att räkna antalet rader det senaste kommandot skickade ut?

Jag kunde göra program | wc -l men det skulle inte visa resultatet för användaren. Så vitt jag vet måste jag göra program; program | wc -l – men programmet tar minst en minut att köra, så jag vill inte behöva göra det mer än en gång bara för att visa ett radantal längst ner.

EDIT:

  • Finns det något sätt att visa utdata när det händer (rad för rad) och sedan returnera ett antal i slutet?

Kommentarer

  • Vad sägs om: låt programmet hålla reda på sin egen produktion och läs bara det värdet från variabeln (t.ex. STDOUT_WRITE_COUNT), eller logga den till en fil / API, i slutet av programmet. WDYT?

Svar

Du kan använda tee för att dela upp utdataströmmen och skicka en kopia till wc och den andra kopian till STDOUT som vanligt.

program | tee >(wc -l) 

>(cmd) är bash-syntax vilket betyder ru n cmd och ersätt >(cmd) bit med sökvägen till (ett namngivet rör kopplat till) det programets STDIN.

Kommentarer

  • >(cmd) är ksh syntax känns också igen av zsh och bash och använder endast namngivna rör på system som inte ' t har /dev/fd/n.
  • @StephaneChazelas Ja, de flesta skalen stöder det, men det ' finns inte POSIX, så det kan ' inte litas på att vara överallt.
  • Ja, jag påpekade bara att processersättning inte var en bash uppfinning som formuleringen i ditt svar kan låta en tro.
  • @TheLibbster Beror på hur du definierar effektiv. Denna metod involverar att leka ytterligare två processer, där sed och awk bara är en. Men tee och wc är båda extremt små (mycket mindre än sed och awk).
  • @TheLibbster ja, enligt några enkla tester gjorde jag precis det ' är faktiskt ungefär dubbelt så snabbt som både metoderna sed och awk. (Jag dd d 100 MB av /dev/urandom till en fil och körde sedan filen genom varje metod flera gånger)

Svar

Ett alternativ är att använda awk, som kan räkna och skriva ut till stdout.

program | awk "{ print } END { print NR }" 

I awk är NR det aktuella radnumret. Du kan åstadkomma detsamma med perl:

program | perl -pe "END {print "$.\n"}" 

Eller sed:

program | sed -n "p;$=" 

Kommentarer

  • Finns det ett sätt att visa utdata när det händer (rad för rad) och sedan returnera ett antal i slutet ?

Svar

mitt favoritalternativ:

program | grep "" -c 

Kommentarer

  • OP kan ha frågat något annat, men jag kom hit och letade efter att bara få ett antal rader och inte ' bryr mig inte om att visa den faktiska produktionen, och detta gör jobbet. Tack!

Svar

Du kan klona stdout på stderr.

program | tee /dev/stderr | wc -l 

På det sättet skickas program” s stdout till tee för att skrivas till stderr, vilket är tryckt på konsolen. tee skriver också data som skickas till den till dess stdout, som skickas till wc.

Svar

Detta kan vara sent. Men jag skulle bara ta upp din uppföljningsfråga om hur man fångar det räknade numret i en variabel.

Det här är vad du vill YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l).

Vi drar nytta av att tee genererar två strömmar här och rikta en till /dev/stderr, som skulle visas på skärmen, och den andra till wc -l, som skulle rapportera antalet rader.

Svar

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) 

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *