Tel het aantal regels uitvoer van het vorige programma

Ik probeer het aantal regels uitvoer te tellen dat een bepaald programma produceert. Het probleem is dat het programma duurt lang en ik wil de uitvoer aan de gebruiker laten zien. Is er een manier om het aantal regels te tellen dat de laatste opdracht heeft uitgevoerd?

Ik zou program | wc -l kunnen doen, maar dat zou de uitvoer niet aan de gebruiker laten zien. Dus voor zover ik weet, moet ik program; program | wc -l doen – maar het programma duurt minstens een minuut, dus ik wil het niet meer dan één keer hoeven doen om een aantal regels onderaan weer te geven.

EDIT:

  • Is er een manier om de uitvoer te laten zien zoals het gebeurt (regel voor regel) en vervolgens een telling aan het einde te retourneren?

Opmerkingen

  • Hoe zit het met: laat het programma zijn eigen uitvoer bijhouden en lees die waarde gewoon uit de variabele (bijv. STDOUT_WRITE_COUNT), of log het in een bestand / API aan het einde van het programma. WDYT?

Antwoord

U kunt tee gebruiken om de uitvoerstroom te splitsen door één kopie te verzenden naar wc en de andere kopie naar STDOUT zoals normaal.

program | tee >(wc -l) 

De >(cmd) is bash-syntaxis wat ru betekent n cmd en vervang het >(cmd) bit door het pad naar (een genoemde pijp verbonden met) de STDIN van dat programma.

Reacties

  • >(cmd) is ksh syntaxis ook herkend door zsh en bash en gebruikt alleen named pipes op systemen die ' t heeft /dev/fd/n.
  • @StephaneChazelas Ja, de meeste shells ondersteunen het, maar het is ' niet in POSIX, dus het kan ' niet worden gebruikt om overal te zijn.
  • Ja, ik wees er net op dat procesvervanging geen bash uitvinding zoals de bewoording in uw antwoord iemand zou doen geloven.
  • @TheLibbster Hangt ervan af hoe u efficiënt definieert. Bij deze methode worden twee extra processen uitgezet, waarbij sed en awk er slechts één zijn. Maar tee en wc zijn beide extreem klein (veel kleiner dan sed en awk).
  • @TheLibbster ja, volgens enkele eenvoudige tests die ik net heb gedaan, ' s eigenlijk ongeveer twee keer zo snel als zowel de sed en awk methoden. (Ik dd d 100mb /dev/urandom naar een bestand en heb dat bestand vervolgens verschillende keren door elke methode gehaald)

Answer

Een optie is om awk te gebruiken, die kan tellen en afdrukken naar stdout.

program | awk "{ print } END { print NR }" 

In awk is NR het huidige regelnummer. U kunt hetzelfde bereiken met perl:

program | perl -pe "END {print "$.\n"}" 

Of sed:

program | sed -n "p;$=" 

Reacties

  • Is er een manier om de uitvoer te laten zien zoals het gebeurt (regel voor regel) en dan een telling aan het einde te retourneren ?

Antwoord

mijn favoriete optie:

program | grep "" -c 

Reacties

  • OP heeft misschien iets anders gevraagd, maar ik kwam hier op zoek naar een telling van het aantal regels uitvoer en deed het niet ' Het is niet belangrijk om de daadwerkelijke output te tonen, en dit is voldoende. Bedankt!

Antwoord

Je kunt stdout klonen op stderr.

program | tee /dev/stderr | wc -l 

Op die manier wordt de stdout van program” doorgesluisd naar tee om te worden geschreven naar stderr, wat afgedrukt op de console. tee schrijft ook de gegevens die ernaar zijn doorgestuurd naar de stdout, die wordt doorgestuurd naar wc.

Answer

Dit zou te laat kunnen zijn. Maar ik wil gewoon je vervolgvraag beantwoorden over hoe je het getelde getal in een variabele kunt opvangen.

Dit is wat je wilt YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l).

We profiteren van tee door hier twee streams te genereren en stuur de ene naar /dev/stderr, die op je scherm zou verschijnen, en de andere naar wc -l, die het aantal regels zou rapporteren.

Antwoord

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) 

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *