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
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)
isksh
syntaxis ook herkend doorzsh
enbash
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
enawk
er slechts één zijn. Maartee
enwc
zijn beide extreem klein (veel kleiner dansed
enawk
). - @TheLibbster ja, volgens enkele eenvoudige tests die ik net heb gedaan, ' s eigenlijk ongeveer twee keer zo snel als zowel de
sed
enawk
methoden. (Ikdd
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)
STDOUT_WRITE_COUNT
), of log het in een bestand / API aan het einde van het programma. WDYT?