
Ich verwende ein Tool ( openocd
), das eine Menge Müll druckt, dann einen einfachen Fortschrittsbalken, der langsam einfache Punkte druckt, und dann wieder etwas Müll.
Ich möchte diese Ausgabe filtern, grep
sodass nur die Zeile mit dem Fortschrittsbalken angezeigt wird und zwar in Echtzeit (d. h. jeder ausgegebene Punkt openocd
wird sofort im Terminal ausgedruckt):
openocd <args> |& grep '^\.'
Das Problem besteht darin, dass es grep
(bestenfalls) zeilengepuffert ist, sodass der Fortschrittsbalken erst angezeigt wird, wenn es abgeschlossen ist.
Wie kann ich das machen grep
, oder gibt es eine Standardalternative, um das zu erreichen? Wenn es einen Weg über openocd
die Konfiguration gibt, wäre das nützlich, obwohl ich eine allgemeinere Lösung bevorzugen würde.
Antwort1
Dies ist eine Art Hack/ungewöhnliche Antwort, da dies höchstwahrscheinlich auf eine nicht sehr saubere Art und Weise möglich ist.
grep
selbst scheint nur dann eine Ausgabe zu drucken, wenn es auf ein Zeilenumbruchzeichen stößt. Ihr Fortschrittsbalken führt bei der Aktualisierung wahrscheinlich kein Zeilenumbruchzeichen ein, daher Ihr Problem.
strace
ist ein Tool zum Anzeigen der Systemaufrufe, die ein Befehl ausführt. Dazu gehören beispielsweise das Lesen und Schreiben von Elementen in den Speicher sowie das Öffnen/Schließen von Dateideskriptoren.
Mit strace
können Sie sehen, worauf ein Prozess zugreift. Wenn Ihre Pipe stout
an weitergeleitet wird grep
, können Sie mit strace
den Text sehen, der an weitergeleitet wird grep
. strace
wird regelmäßig die Ausgabe des weitergeleiteten Befehls gesendet, und Sie können diese Ausgabe abhören und anzeigen. Ich habe mit getestet rsync --progress
, was auf ein ähnliches Szenario zu stoßen scheint. Ich habe grep
auf verwendet ##%
, weil das rsync
verwendet wird, um den Fortschritt anzuzeigen.
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%"
Wenn Sie diesen Befehl ausführen, werden Sie feststellen, dass die strace
Ausgabe nicht schön ist, aber dass bei meiner Verwendung strace
einige read
Signale erfasst wurden rsync
, die grep
normalerweise nicht ausgegeben würden write
. Es wurden Signale für 0 %, 21 %, 45 %, 68 %, 91 % und 100 % angezeigt read
und die Aktualisierung schien etwa jede Sekunde zu erfolgen (wahrscheinlich abhängig davon, wie oft rsync
der Fortschritt aktualisiert wird).
Damit kann man grep
die strace
Ausgabe, die nicht sehr schön ist, durch einen erneuten Aufruf grep
wieder zurücknehmen.
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"
Das 2>&1
ist wichtig, weil strace
es auf ausgibt stderr
. Das > /dev/null
leitet auf um stdout
, /dev/null
um zu verhindern, dass die Ausgabe des ersten grep
gemeldet wird. Das Endergebnis davon war die folgende Ausgabe:
0%
21%
45%
68%
91%
100%
Sie müssen das austauschen grep
, aber es scheint, als würde es funktionieren. Es ist nicht schön, aber es funktioniert und umgeht die Einschränkungen von grep
. Es scheint, als wäre ein grep -f
, das wie funktioniert, praktisch (ich weiß , dass es bereits verwendet wird).tail -f
grep -f
Die erste besteht hauptsächlich darin, den zu sendenden grep
Text herauszufiltern , da in S -Aufrufen nur die übereinstimmenden Zeilen aufgelistet werden . Sie benötigen jedoch auch etwas, durch das der Text laufen kann, damit Sie ihn beobachten können.strace
read
strace
read
strace
Antwort2
Ich gehe näher auf die Centimane-Antwort ein, da die endgültige Antwort ziemlich kompliziert ist.
Das war schon ziemlich hackig... jetzt wird es richtig beschissen:
make flash \
|& strace -e trace=read grep -e "^\." -e rror \
|& stdbuf -o0 sed -ne 's/^.*"\.".*/\./p;/rror/p' \
| stdbuf -o0 tr -d '\n' \
; echo
Das make flash
oben genannte ruft also auf openocd
;
strace
verwendet den oben erläuterten Hack von Centimane;
sed
read(0, ".", xxx)
Zeilen durch einzelne ersetzen .
;
tr
hält alles .
in einer Zeile und das letzte Echo setzt das einzige EOL.
Darüber hinaus werden sed
und tr
aufgerufen stdbuf -o0
, wodurch die Größe des Standardausgabepuffers auf 0 gesetzt wird (da EOL entfernt wurde). grep/sed
Außerdem werden sie angepasst (e)rror
, um im Fehlerfall Datenmüll auszudrucken.
Ich habe versucht, diesen ganzen Ballast auf das absolute Minimum zu reduzieren, aber es ist mir nicht besser gelungen.
Beachten Sie auch, dass ich zsh/Ubuntu 14.04 verwende und nicht sicher bin, ob dies auf anderen Unix-Versionen funktioniert.