Jeg prøver å telle antall linjer med utgang et bestemt program produserer. Problemet er at programmet tar lang tid å kjøre, og jeg vil vise utdataene til brukeren. Er det en måte å telle antall linjer den siste kommandoen som ble sendt ut?
Jeg kunne gjøre program | wc -l
men det ville ikke vise utdataene til brukeren. Så vidt jeg vet, må jeg gjøre program; program | wc -l
– men programmet tar minst et minutt å kjøre, så jeg vil ikke måtte gjøre det mer enn en gang bare for å vise en linjetelling nederst.
EDIT:
- Er det en måte å vise utdata når det skjer (linje for linje) og deretter returnere en telling på slutten?
Kommentarer
Svar
Du kan bruke tee
til å dele utstrømmen og sende en kopi til wc
og den andre kopien til STDOUT som vanlig.
program | tee >(wc -l)
>(cmd)
er bash-syntaks som betyr ru n cmd
og erstatt >(cmd)
bit med banen til (et navngitt rør koblet til) det programets STDIN.
Kommentarer
-
>(cmd)
erksh
syntaks også gjenkjent avzsh
ogbash
og bruker bare navngitte rør på systemer som ikke ' t har/dev/fd/n
. - @StephaneChazelas Ja, de fleste skjell støtter det, men det ' er ikke i POSIX, så det kan ' ikke stole på å være overalt.
- Ja, jeg påpekte bare at prosesserstatning ikke var en
bash
oppfinnelsen som ordlyden i svaret ditt kan la en tro. - @TheLibbster Avhenger av hvordan du definerer effektiv. Denne metoden innebærer gyting av to tilleggsprosesser, der
sed
ogawk
bare er en. Mentee
ogwc
er begge ekstremt små (mye mindre ennsed
ogawk
). - @TheLibbster ja, ifølge noen enkle tester jeg nettopp gjorde, er det ' omtrent dobbelt så raskt som både
sed
ogawk
-metodene. (Jegdd
d 100 MB av/dev/urandom
til en fil og kjørte deretter filen gjennom hver metode flere ganger)
Svar
Et alternativ er å bruke awk, som kan telle og skrive ut til stdout.
program | awk "{ print } END { print NR }"
I awk
er NR gjeldende linjenummer. Du kan oppnå det samme med perl:
program | perl -pe "END {print "$.\n"}"
Eller sed
:
program | sed -n "p;$="
Kommentarer
- Er det en måte å vise utdata når det skjer (linje for linje) og deretter returnere en telling på slutten ?
Svar
mitt favorittalternativ:
program | grep "" -c
Kommentarer
- OP kan ha bedt om noe annet, men jeg kom hit på jakt etter bare å få et antall antall linjer og ikke ' bryr meg ikke om å vise den faktiske produksjonen, og dette gjør jobben. Takk!
Svar
Du kan klone stdout på stderr.
program | tee /dev/stderr | wc -l
På den måten blir program
» s stdout piped til tee
som skal skrives til stderr, som er trykt på konsollen. tee
skriver også dataene som ledes til den til sin stdout, som ledes til wc
.
Svar
Dette kan være sent. Men jeg vil bare ta opp oppfølgingsspørsmålet ditt om hvordan du kan fange det tellede tallet i en variabel.
Dette vil du ha YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l)
.
Vi benytter oss av at tee
genererer to strømmer her og led den ene til /dev/stderr
, som vises på skjermen, og den andre til wc -l
, som rapporterer antall linjer.
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 logg den til en fil / API, på slutten av programmet. WDYT?