Wie kann ich eine Ausgabe, die einen Fortschrittsbalken enthält, in Echtzeit greppen?

Wie kann ich eine Ausgabe, die einen Fortschrittsbalken enthält, in Echtzeit greppen?

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, grepsodass nur die Zeile mit dem Fortschrittsbalken angezeigt wird und zwar in Echtzeit (d. h. jeder ausgegebene Punkt openocdwird 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 openocddie 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.


grepselbst 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.

straceist 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 stracekönnen Sie sehen, worauf ein Prozess zugreift. Wenn Ihre Pipe stoutan weitergeleitet wird grep, können Sie mit straceden Text sehen, der an weitergeleitet wird grep. stracewird 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 grepauf verwendet ##%, weil das rsyncverwendet 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 straceAusgabe nicht schön ist, aber dass bei meiner Verwendung straceeinige readSignale erfasst wurden rsync, die grepnormalerweise nicht ausgegeben würden write. Es wurden Signale für 0 %, 21 %, 45 %, 68 %, 91 % und 100 % angezeigt readund die Aktualisierung schien etwa jede Sekunde zu erfolgen (wahrscheinlich abhängig davon, wie oft rsyncder Fortschritt aktualisiert wird).

Damit kann man grepdie straceAusgabe, die nicht sehr schön ist, durch einen erneuten Aufruf grepwieder zurücknehmen.

rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"

Das 2>&1ist wichtig, weil stracees auf ausgibt stderr. Das > /dev/nullleitet auf um stdout, /dev/nullum zu verhindern, dass die Ausgabe des ersten grepgemeldet 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 -fgrep -f

Die erste besteht hauptsächlich darin, den zu sendenden grepText 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.stracereadstracereadstrace

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 flashoben genannte ruft also auf openocd;

straceverwendet den oben erläuterten Hack von Centimane;

sedread(0, ".", xxx)Zeilen durch einzelne ersetzen .;

trhält alles .in einer Zeile und das letzte Echo setzt das einzige EOL.

Darüber hinaus werden sedund traufgerufen stdbuf -o0, wodurch die Größe des Standardausgabepuffers auf 0 gesetzt wird (da EOL entfernt wurde). grep/sedAuß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.

verwandte Informationen