Jeg prøver at tælle antallet af outputlinjer, som et bestemt program producerer. Problemet er, programmet det tager lang tid at køre, og jeg vil vise output til brugeren. Er der en måde at tælle antallet af linjer, den sidste kommando udsendte?
Jeg kunne gøre program | wc -l
men det ville ikke vise output til brugeren. Så vidt jeg ved, skal jeg gøre program; program | wc -l
– men programmet tager mindst et minut at køre, så jeg ønsker ikke at skulle gøre det mere end en gang bare for at vise et linjetælling i bunden.
EDIT:
- Er der en måde at vise output på, når det sker (linje for linje) og derefter returnere et antal i slutningen?
Kommentarer
Svar
Du kan bruge tee
til at opdele outputstrømmen og sende en kopi til wc
og den anden kopi til STDOUT som normalt.
program | tee >(wc -l)
>(cmd)
er bash-syntaks, hvilket betyder ru n cmd
og udskift >(cmd)
bit med stien til (et navngivet rør forbundet til) det program “s STDIN.
Kommentarer
-
>(cmd)
erksh
syntaks også genkendt afzsh
ogbash
og bruger kun navngivne rør på systemer, der ikke ' t har/dev/fd/n
. - @StephaneChazelas Ja, de fleste skaller understøtter det, men det ' er ikke i POSIX, så det kan ' ikke stole på at være overalt.
- Ja, jeg påpegede bare, at procesudskiftning ikke var en
bash
opfindelse som formuleringen i dit svar kan lade en tro. - @TheLibbster Afhænger af, hvordan du definerer effektiv. Denne metode involverer gydning af yderligere 2 processer, hvor
sed
ogawk
kun er én. Mentee
ogwc
er begge ekstremt små (meget mindre endsed
ogawk
). - @TheLibbster ja, ifølge nogle enkle tests gjorde jeg lige, det ' er faktisk omkring dobbelt så hurtigt som både
sed
ogawk
-metoderne. (Jegdd
d 100 MB af/dev/urandom
til en fil og kørte derefter filen gennem hver metode flere gange)
Svar
En mulighed er at bruge awk, som kan tælle og udskrive til stdout.
program | awk "{ print } END { print NR }"
I awk
er NR det aktuelle linjenummer. Du kan opnå det samme med perl:
program | perl -pe "END {print "$.\n"}"
Eller sed
:
program | sed -n "p;$="
Kommentarer
- Er der en måde at vise output på, når det sker (linje for linje) og derefter returnere et antal i slutningen ?
Svar
min yndlingsmulighed:
program | grep "" -c
Kommentarer
- OP har muligvis spurgt noget andet, men jeg kom her på udkig efter bare at få et antal optag af linjer og ' er ligeglad med at vise den faktiske output, og dette gør jobbet. Tak!
Svar
Du kan klone stdout på stderr.
program | tee /dev/stderr | wc -l
På den måde ledes program
” s stdout til tee
for at blive skrevet til stderr, hvilket er trykt på konsollen. tee
skriver også data, der sendes til den til sin stdout, som ledes til wc
.
Svar
Dette kan være sent. Men jeg vil bare adressere dit opfølgningsspørgsmål om, hvordan man fanger det tællede tal i en variabel.
Dette er hvad du vil have YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l)
.
Vi drager fordel af tee
genererer to streams her og diriger den ene til /dev/stderr
, som vises på skærmen, og den anden til wc -l
, som rapporterer antallet af 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 log det til en fil / API i slutningen af programmet. WDYT?