Inzwischen ist die unbrauchbare Verwendung von cat
Awards sehr bekannt, und es wird auch eine unbrauchbare Verwendung vonecho
(für diese Frage nicht relevant) erwähnt. Ich frage mich, ob es einen "Useless Use of echo
in Bash Award" geben sollte: Piping scheint nach einigen hochgradig unwissenschaftlichen Messungen viel langsamer zu sein als Heredocs und Herestrings:
Heredocs:
for reps in 1 2 3 do time for i in {1..1000} do cat <<'END' test string END done > /dev/null done real 0m1.786s user 0m0.212s sys 0m0.332s real 0m1.817s user 0m0.232s sys 0m0.332s real 0m1.846s user 0m0.256s sys 0m0.320s
Herestrings
for reps in 1 2 3 do time for i in {1..1000} do cat <<< 'test string' done > /dev/null done real 0m1.932s user 0m0.280s sys 0m0.288s real 0m1.956s user 0m0.248s sys 0m0.348s real 0m1.968s user 0m0.268s sys 0m0.324s
Umleitung
for reps in 1 2 3 do time for i in {1..1000} do echo 'test string' | cat done > /dev/null done real 0m3.562s user 0m0.416s sys 0m0.548s real 0m3.924s user 0m0.384s sys 0m0.604s real 0m3.343s user 0m0.400s sys 0m0.552s
Im Allgemeinen haben Heredocs und Herestrings ungefähr dieselbe Geschwindigkeit (dies ist nur ein Datensatz aus mehreren Tests), während die Umleitung durchweg mehr als 50% langsamer ist. Verstehe ich etwas falsch oder kann dies als allgemeine Regel für Befehle zum Lesen von Standardeingaben in Bash verwendet werden?
seq
" der Auszeichnung ;-)cat <<END
vs.cat <<< "test string"
vs.echo "test string" | cat
odercat <<'END'
vs.cat <<< 'test string'
vs. vergleichen solltenecho 'test string' | cat
, um die gleiche Anzahl von Erweiterungen zu erhalten, die von der Shell für die Zeichenfolgen ausgeführt werden.$(seq $reps)
?Antworten:
Konzentrieren wir uns zunächst auf die Leistung. Ich habe Benchmarks für ein etwas anderes Programm auf einem ansonsten meist inaktiven x86_64-Prozessor mit Debian Squeeze ausgeführt.
herestring.bash
Verwenden Sie einen Herestring, um eine Eingabezeile zu übergeben:heredoc.bash
Verwenden eines Heredocs zum Übergeben einer Eingabezeile:echo.bash
Verwenden Sieecho
und eine Pipe, um eine Eingabezeile zu übergeben:Zum Vergleich habe ich auch die Skripte unter ATT ksh93 und unter dash zeitlich festgelegt (außer
herestring.bash
, weil dash keine Herestrings hat).Hier ist der Median des Dreifachen:
Schlussfolgerungen:
echo
und eine Pfeife ist merklich, aber nicht dramatisch schneller. (Denken Sie daran, dass dies ein Spielzeugprogramm ist: In einem echten Programm würde die meiste Verarbeitungszeit in dem liegen, wofür dertr
Aufruf hier steht.)Über die Leistung hinaus gibt es auch Klarheit und Portabilität.
<<<
ist eine ksh93 / bash / zsh-Erweiterung, die weniger bekannt ist alsecho … |
oder<<
. Es funktioniert nicht in ksh88 / pdksh oder in POSIX sh.Der einzige Ort, an dem
<<<
es wahrscheinlich viel klarer ist, befindet sich in einem Heredoc:vs
(Die meisten Shells schaffen es nicht, die Klammer am Ende der Zeile zu schließen, die enthält
<<EOF
.)quelle
<<<
ausrc
der Bourne-ähnlichen Shell-Welt stammt und zuerst von der Bourne-ähnlichen Shell-Welt gebracht wurdezsh
.rc
hat keinen Newline, aber alle hinzufügenbash
,zsh
undksh93
tun AFAICT.rc
Es verwendet ein Rohr, währendbash
,zsh
undksh93
eine temporäre Datei wie für Heredocs verwenden.<<<
noch weniger nützlich.zsh
es eine Optimierung gibt,=(<<<foo)
um effektiv eine temporäre Datei zu erstellen, die "foo" enthält, bei der ein Prozess nicht wie gewohnt gegabelt wird=(echo foo)
.<<<
.Ein weiterer Grund für die Verwendung von Heredocs (wenn Sie nicht genug hatten) ist, dass das Echo fehlschlagen kann, wenn der Stream nicht verwendet wird. Erwägen Sie die bash-
pipefail
Option:/bin/true
Verbraucht nicht die Standardeingabe, wird aberecho yawn
dennoch abgeschlossen. Wenn das Echo jedoch aufgefordert wird, viele Daten zu drucken, wird es erst abgeschlossen, wenn Folgendestrue
abgeschlossen ist:141 ist SIGPIPE (128 + 13) (128 wird hinzugefügt, weil bash dies gemäß bash (1) tut:
Heredocs haben dieses Problem nicht:
quelle
pipefail
Standardeinstellung ausgeschaltet ist!pipefail
am Anfang jedes Skripts. Gib mir alle Fehler!Ein Grund, warum Sie Echo verwenden möchten, besteht darin, das Zeilenumbruchzeichen, das an das Ende von heredocs und herestrings angehängt wird, zu steuern:
Drei Zeichen
foo
haben die Länge 3:Ein Drei-Zeichen-Herestring besteht jedoch aus vier Zeichen:
Ein dreistelliger Heredoc:
Das vierte Zeichen ist ein Newline-
0x0a
Zeichen.Irgendwie fügt sich das magisch in die Art ein, wie Bash diese Zeilenumbrüche entfernt, wenn Ausgaben aus einer Sub-Shell abgerufen werden:
Hier ist ein Befehl, der vier Zeichen zurückgibt:
foo
und\n
. Das '\ n' wird per Echo hinzugefügt. Es wird immer ein Zeilenumbruchzeichen hinzugefügt, es sei denn, Sie geben die-n
Option an:Wenn Sie dies jedoch einer Variablen zuweisen, wird die durch echo hinzugefügte nachgestellte Zeile entfernt:
Wenn Sie also Dateien und Variablen mischen und in Berechnungen verwenden (z. B. können Sie keine Heredocs oder Herestrings verwenden, da diese eine neue Zeile hinzufügen.
Wenn Sie die if-Anweisung in read ändern
dann ist der Test bestanden.
quelle