‚grep‘ funktioniert nicht mit ‚Zeit‘?

‚grep‘ funktioniert nicht mit ‚Zeit‘?

Warum wird time ls | grep realdies ausgegeben?

real    0m0.002s
user    0m0.000s
sys     0m0.002s

statt nur

real    0m0.002s

Wenn ich tippe

echo -e 'real\t0m0.002s\nuser\t0m0.000s\nsys\t0m0.002s\n' | grep real

Ich bekomme, was ich erwarte, nämlich

real    0m0.002s

Ich habe festgestellt, dass das funktioniert

(time ls)  2>&1 > /dev/null | grep real

Was macht dieser Befehl?

Antwort1

Warum time ls | grep realfunktioniert es nicht wie erwartet?

timeist ein bashreserviertes Wort und verhält sich anders als /usr/bin/time.

Wenn das reservierte Wort „time“ einer Pipeline vorangestellt ist, werden die verstrichene sowie die von der Ausführung verbrauchte Benutzer- und Systemzeit gemeldet.wenn die Pipeline endet.

Quellebash(1): GNU Bourne-Again SHell - Linux-Manpage

Darüber hinaus timeerfolgt die Ausgabe an den Standardfehler und nicht an die Standardausgabe.

Verwenden Sie den folgenden Befehl:

(time ls) 2>&1 >/dev/null | grep real 

Anmerkungen:

  • Das („und“ )gruppiert die time„und“ ls-Befehle (sodass diese Befehle zuerst ausgewertet werden)

  • 2>&1 >/dev/nullleitet stderr zuerst zu stdout (das ist die Pipe) um und leitet stdout dann zu um /dev/null.

    Also geht stderr zur Pipe und stdout geht nirgendwohin.


Weitere Informationen

Antwort2

Ja, es funktioniert, aber es erfordert eine gewisse E/A-Umleitung :)

$ exec 3>&1 4>&2
{ time sleep 1 1>&3 2>&4; } 2>&1 |
    grep 'real'    
exec 3>&- 4>&-

Ausgabe :

real    0m1,003s

LesenBash-FAQ#32UndTutorial zur E/A-Umleitung


Ein viel einfacherer Weg:

$ TIMEFORMAT=%R
$ time sleep 1
1,003

Antwort3

Hier gibt es zwei Probleme.

Erstens und am wichtigsten: „time“ sendet seine Ausgabe an stderr (Standardfehler) und nicht an stdout, sodass sie nicht von normalen Umleitungsbefehlen erfasst wird, sofern Sie keine besonderen Maßnahmen ergreifen.

Zweitens ist time kein normales Programm, sondern ein spezieller integrierter Befehl, der direkt von der Shell interpretiert wird (für Shells wie bash, csh, tcsh usw.). Es funktioniert daher auf nicht standardmäßige Weise und misst die Zeit für den gesamten Rest der Befehlszeile (es sei denn, Sie verwenden eine sehr ungewöhnliche Shell).

Um das gewünschte Ergebnis zu erhalten (mit Bash), müssen Sie Folgendes verwenden:

(time ls) 2>&1 | grep real

Dadurch wird das "ls" in einer Subshell ausgeführt und die Zeit gemessen [(Zeit ls)], Standardfehler an Standardausgabe senden[ 2>&1 ], und senden Sie dann Standard an "grep" [|grep].

Der letzte von Ihnen verwendete Teil „>?dev/null“ verwirft die normale Ausgabe des Befehls ls selbst, falls dieser das Wort „real“ enthielt.

Antwort4

Es scheint, dass timedirekt in die Konsole und nicht in geschrieben wird stdout, was bedeutet, dass die Ausgabe des Befehls oder der Pipeline durch das Hinzufügen nicht beeinflusst wird time.

Daher grepwird der Zeitbericht, der ohnehin nach grepAbschluss generiert wird, nie angezeigt, da die gesamte Pipeline zeitlich gesteuert wird.

verwandte Informationen