Tell antall linjer med utdata fra forrige program

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

  • Hva med: la programmet holde oversikt over sin egen produksjon og bare lese den verdien fra variabelen (f.eks. STDOUT_WRITE_COUNT), eller logg den til en fil / API, på slutten av programmet. WDYT?

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) er ksh syntaks også gjenkjent av zsh og bash 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 og awk bare er en. Men tee og wc er begge ekstremt små (mye mindre enn sed og awk).
  • @TheLibbster ja, ifølge noen enkle tester jeg nettopp gjorde, er det ' omtrent dobbelt så raskt som både sed og awk -metodene. (Jeg dd 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) 

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *