Grep kann die Ausgabe an eine Pipe nicht durchführen?

Grep kann die Ausgabe an eine Pipe nicht durchführen?

Ich habe Probleme mit der Grep-Filterung der Make-Ausgabe. Insbesondere

make target 2>&1 | grep -E --color=never "^make.*"

funktioniert wie erwartet, aber Folgendes druckt keine Ausgabe auf der Konsole:

make target 2>&1 | grep -E --color=never "^make.*" | cat

Übersehe ich etwas Offensichtliches? Warum gibt der erste Befehl etwas aus, der zweite aber nicht? Hat das etwas mit einer Art IO-Pufferung zu tun? Oder bin ich einfach nur dumm?

[BEARBEITEN]: catist nur ein minimaler Testfallplatzhalter für den eigentlichen Befehl, den ich verwenden möchte.

[BEARBEITEN]:Dies scheint bei grep kein Problem zu sein, da das Ersetzen durchackführt zum gleichen Verhalten.

[BEARBEITEN]:Skript, für das die Katze ein Platzhalter ist:

#!/bin/bash
cat - \
 | grep -E --color=never "^.*warning:.*|^.*error:.*|^make.*[Ee]rror.*|^make.*" \
 | hilite.sh -r "^.*warning:.*" -f yellow -B \
 | hilite.sh -r "^.*error:.*" -f red -B \
 | hilite.sh -r "^make.*[Ee]rror.*" -f red -B \
 | hilite.sh -r "^make.*" -f magenta

[BEARBEITEN]:Ich denke, es ist ein Puffer-/E/A-Problem. Ich lasse den Build über die Woche laufen und werde sehen, ob er die Ausgabe schließlich dorthin bringt, wo sie hin soll!

Antwort1

Wahrscheinlich greperkennt es, dass es nicht auf ein TTY schreibt, und puffert daher mehr Ausgabe, anstatt im üblichen zeilengepufferten Modus zu arbeiten (d. h. Sie sehen jede Zeile, sobald sie gefunden wird). Dieses Verhalten ist effizienter, da es zu weniger write()Systemaufrufen führt, aber wenn Sie ein Benutzer sind, der auf eine Pipeline-Ausgabe wartet, kann es etwas irreführend sein.

Wenn Sie GNU verwenden grep(und aufgrund Ihres Linux-Tags gehe ich davon aus), sehen Sie sich die --line-bufferedOption an, die grepdie Arbeit im bekannteren zeilengepufferten Modus erzwingt. Dies könnte technisch gesehen die Leistung verringern grep(wie auf der Manpage vermerkt), aber da Sie sich die Ausgabe eines Live-Builds ansehen, bezweifle ich, dass es in dieser Hinsicht einen Unterschied machen wird.

Antwort2

Sie sind nicht sicher, was Ihr Befehl tun soll. Soll er alle Dateien caten, deren Dateiname „make.*“ enthält?

Versuchen Sie, das catfür xargs cat? zu ändern.

Antwort3

Sie könnten beispielsweise mit experimentieren unbuffer,

make target 2>&1 | unbuffer -p grep -E --color=never "^make.*" | cat

verwandte Informationen