Tæl antallet af outputlinjer fra det forrige program

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

  • Hvad med: at programmet holder styr på sin egen output og bare læser den værdi fra variablen (f.eks. STDOUT_WRITE_COUNT), eller log det til en fil / API i slutningen af programmet. WDYT?

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) er ksh syntaks også genkendt af zsh og bash 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 og awk kun er én. Men tee og wc er begge ekstremt små (meget mindre end sed og awk).
  • @TheLibbster ja, ifølge nogle enkle tests gjorde jeg lige, det ' er faktisk omkring dobbelt så hurtigt som både sed og awk -metoderne. (Jeg dd 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) 

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *