Warum wird time ls | grep real
dies 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 real
funktioniert es nicht wie erwartet?
time
ist ein bash
reserviertes 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 time
erfolgt 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 dietime
„und“ls
-Befehle (sodass diese Befehle zuerst ausgewertet werden)2>&1 >/dev/null
leitet 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
- Ein AZ-Index der Bash-Befehlszeile für Linux- Ein hervorragendes Nachschlagewerk zu allen Themen rund um die Bash-Befehlszeile.
- Klammern- Verwenden von Klammern zum Gruppieren und Erweitern von Ausdrücken.
- Syntax-Umleitung- Umleitung und Prozesssubstitution.
- Bash-Referenzhandbuch: Umleitungen
- Illustriertes Umleitungstutorial [Bash Hackers Wiki]
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 time
direkt 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 grep
wird der Zeitbericht, der ohnehin nach grep
Abschluss generiert wird, nie angezeigt, da die gesamte Pipeline zeitlich gesteuert wird.