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
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)
ärksh
syntax känns också igen avzsh
ochbash
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
ochawk
bara är en. Mentee
ochwc
är båda extremt små (mycket mindre änsed
ochawk
). - @TheLibbster ja, enligt några enkla tester gjorde jag precis det ' är faktiskt ungefär dubbelt så snabbt som både metoderna
sed
ochawk
. (Jagdd
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)
STDOUT_WRITE_COUNT
), eller logga den till en fil / API, i slutet av programmet. WDYT?