À présent, l' utilisation inutile du cat
prix est très bien connue, et il est également fait mention d'une utilisation inutile deecho
(non pertinente pour cette question). Je me demande s'il devrait y avoir une "utilisation inutile de echo
in Bash Award": la tuyauterie semble être beaucoup plus lente que les heredocs et les herestrings selon certaines mesures très non scientifiques:
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
Redirection
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
En général, les heredocs et les herestrings sont à peu près à la même vitesse (ce n'est qu'un ensemble de données provenant de plusieurs tests) tandis que la redirection est systématiquement plus de 50% plus lente. Suis-je en train de mal comprendre quelque chose, ou cela pourrait-il être utilisé comme règle générale pour les commandes lisant l'entrée standard dans Bash?
seq
récompense pour " utilisation inutile de " ;-)cat <<END
vscat <<< "test string"
vsecho "test string" | cat
oucat <<'END'
vscat <<< 'test string'
vsecho 'test string' | cat
pour avoir la même quantité d'extensions effectuées par le shell sur les chaînes.$(seq $reps)
?Réponses:
Tout d'abord, concentrons-nous sur les performances. J'ai exécuté des tests de performance pour un programme légèrement différent sur un processeur x86_64 par ailleurs essentiellement inactif exécutant Debian Squeeze.
herestring.bash
, en utilisant une chaîne héritée pour passer une ligne d'entrée:heredoc.bash
, en utilisant un hérédoc pour passer une ligne d'entrée:echo.bash
, en utilisantecho
et un tuyau pour passer une ligne d'entrée:À titre de comparaison, j'ai également chronométré les scripts sous ATT ksh93 et sous tiret (sauf pour
herestring.bash
, car le tiret n'a pas ses chaînes).Voici la médiane de trois fois:
Conclusions:
echo
et une pipe est sensiblement, mais pas beaucoup plus rapide. (Gardez à l'esprit qu'il s'agit d'un programme jouet: dans un programme réel, la majeure partie du temps de traitement serait dans tout ce que l'tr
appel représente ici.)Au-delà des performances, il y a aussi la clarté et la portabilité.
<<<
est une extension ksh93 / bash / zsh qui est moins connue queecho … |
ou<<
. Cela ne fonctionne pas dans ksh88 / pdksh ou dans POSIX sh.Le seul endroit où il
<<<
est sans doute nettement plus clair est à l'intérieur d'un hérédoc:contre
(La plupart des shells ne peuvent pas faire face à la fermeture de la parenthèse à la fin de la ligne contenant
<<EOF
.)la source
<<<
vient derc
, et a été introduit pour la première fois dans le monde de la coque Bournezsh
.rc
n'a pas ajouté de nouvelle ligne de fin, mais tousbash
,zsh
etksh93
font AFAICT.rc
utilise un canal là-bas, tandis quebash
,zsh
etksh93
utilisez un fichier temporaire comme pour les heredocs.<<<
encore moins utile.zsh
a une optimisation=(<<<foo)
pour créer efficacement un fichier temporaire qui contient "foo" qui n'implique pas de bifurquer un processus comme le=(echo foo)
ferait.<<<
.Une autre raison d'utiliser heredocs (si vous n'en avez pas assez) est que l'écho peut échouer si le flux n'est pas consommé. Pensez à avoir l'
pipefail
option bash ' :/bin/true
ne consomme pas son entrée standard, mais seecho yawn
termine néanmoins. Cependant, si l'écho est invité à imprimer un grand nombre de données, il ne se terminera qu'après latrue
fin:141 est SIGPIPE (128 + 13) (128 étant ajouté car bash le fait selon bash (1):
Heredocs n'a pas ce problème:
la source
pipefail
valeurs par défaut soient éteintes!pipefail
en haut de chaque script. Donne-moi toutes les erreurs!Une raison pour laquelle vous voudrez peut-être utiliser l'écho est d'exercer un certain contrôle sur le caractère de nouvelle ligne qui est ajouté à la fin des heredocs et herestrings:
Trois caractères
foo
ont une longueur de 3:Cependant, une chaîne de caractères à trois caractères comprend quatre caractères:
Un hérédoc à trois caractères aussi:
Le quatrième caractère est un
0x0a
caractère de nouvelle ligne .D'une manière ou d'une autre, cela correspond magiquement à la façon dont bash supprime ces caractères de nouvelle ligne lors de la récupération de la sortie d'un sous-shell:
Voici une commande qui renvoie quatre caractères:
foo
et\n
. Le '\ n' est ajouté par echo, il ajoute toujours un caractère de nouvelle ligne sauf si vous spécifiez l'-n
option:Cependant, en l'affectant à une variable, la nouvelle ligne de fin ajoutée par echo est supprimée:
Donc, si vous mélangez des fichiers et des variables et les utilisez dans des calculs (par exemple, vous ne pouvez pas utiliser des heredocs ou des herestrings, car ils ajouteront une nouvelle ligne.
Si vous modifiez l'instruction if pour lire
puis le test réussit.
la source