Ich versuche, die Anzahl der Ausgabezeilen zu zählen, die ein bestimmtes Programm erzeugt. Das Problem ist das Programm Die Ausführung dauert lange und ich möchte dem Benutzer die Ausgabe anzeigen. Gibt es eine Möglichkeit, die Anzahl der Zeilen zu zählen, die der zuletzt ausgegebene Befehl ausgegeben hat?
Ich könnte program | wc -l
ausführen, aber das würde dem Benutzer die Ausgabe nicht anzeigen. Soweit ich weiß, muss ich program; program | wc -l
ausführen – aber die Ausführung des Programms dauert mindestens eine Minute, sodass ich es nicht mehr als einmal ausführen muss um eine Zeilenanzahl unten anzuzeigen.
BEARBEITEN:
- Gibt es eine Möglichkeit, die Ausgabe (zeilenweise) anzuzeigen und am Ende eine Zählung zurückzugeben?
Kommentare
- Wie wäre es: Lassen Sie das Programm seine eigene Ausgabe verfolgen und lesen Sie einfach diesen Wert aus der Variablen (z
STDOUT_WRITE_COUNT
) oder protokollieren Sie es in einer Datei / API am Ende des Programms. WDYT?
Antwort
Mit tee
können Sie den Ausgabestream aufteilen und eine Kopie an wc
und senden die andere Kopie an STDOUT wie gewohnt.
program | tee >(wc -l)
Die >(cmd)
ist Bash-Syntax, was ru bedeutet n cmd
und ersetzen Sie das Bit >(cmd)
durch den Pfad zur STDIN des Programms (eine mit ihm verbundene Named Pipe).
.
Kommentare
-
>(cmd)
ist dieksh
-Syntax, die auch vonzsh
undbash
und verwendet nur Named Pipes auf Systemen, die nicht ' t have/dev/fd/n
. - @StephaneChazelas Ja, die meisten Shells unterstützen dies, aber ' ist nicht in POSIX, damit ' nicht überall verwendet werden kann.
- Ja, ich habe nur darauf hingewiesen, dass die Prozessersetzung keine Erfindung als Wortlaut in Ihrer Antwort könnte einen glauben lassen.
- @TheLibbster Hängt davon ab, wie Sie effizient definieren. Bei dieser Methode werden zwei zusätzliche Prozesse erzeugt, wobei
sed
undawk
nur einer sind. Abertee
undwc
sind beide extrem klein (viel kleiner alssed
undawk
). - @TheLibbster Ja, nach einigen einfachen Tests, die ich gerade durchgeführt habe, ist ' tatsächlich ungefähr doppelt so schnell als die Methoden
sed
undawk
. (Idd
d 100 MB/dev/urandom
in eine Datei und führte diese Datei dann mehrmals durch jede Methode)
Antwort
Eine Option ist die Verwendung von awk, mit der gezählt und nach stdout gedruckt werden kann.
program | awk "{ print } END { print NR }"
In awk
ist NR die aktuelle Zeilennummer. Sie können dasselbe mit Perl erreichen:
program | perl -pe "END {print "$.\n"}"
Oder sed
:
program | sed -n "p;$="
Kommentare
- Gibt es eine Möglichkeit, die Ausgabe (zeilenweise) anzuzeigen und am Ende eine Zählung zurückzugeben ?
Antwort
meine Lieblingsoption:
program | grep "" -c
Kommentare
- OP hat vielleicht etwas anderes gefragt, aber ich bin hierher gekommen, um nur die Anzahl der ausgegebenen Zeilen zu ermitteln, und habe nicht ' Es ist nicht wichtig, die tatsächliche Ausgabe anzuzeigen, und dies erledigt den Job. Danke!
Antwort
Sie können stdout auf stderr klonen.
program | tee /dev/stderr | wc -l
Auf diese Weise wird das stdout von program
an tee
weitergeleitet, um in stderr geschrieben zu werden tee
schreibt auch die an sie weitergeleiteten Daten in die Standardausgabe, die an wc
.
Antwort
Dies könnte zu spät sein. Ich möchte jedoch nur Ihre Folgefrage beantworten, wie die gezählte Zahl in einer Variablen abgefangen werden kann.
Dies ist, was Sie wollen YOUR_VAR=$(PROGRAM | tee /dev/stderr | wc -l)
.
Wir nutzen den Vorteil, dass tee
hier und hier zwei Streams generiert Richten Sie eine an /dev/stderr
, die auf Ihrem Bildschirm angezeigt wird, und die andere an wc -l
, die die Anzahl der Zeilen angibt.
Antwort
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)