En este momento, el uso inútil del cat
premio es muy conocido, y también se menciona el uso inútil deecho
(no relevante para esta pregunta). Me pregunto si debería haber un "Premio al uso inútil echo
en Bash": las tuberías parecen ser mucho más lentas que los heredocs y los herejes según algunas mediciones muy poco científicas:
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
Herejías
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
Redireccionamiento
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 general, los heredocs y herestrings tienen aproximadamente la misma velocidad (este es solo un conjunto de datos de varias pruebas), mientras que la redirección es consistentemente un 50% más lenta. ¿Estoy malinterpretando algo, o podría usarse esto como una regla general para los comandos que leen la entrada estándar en Bash?
seq
premio de " uso inútil de " ;-)cat <<END
frente acat <<< "test string"
frenteecho "test string" | cat
ocat <<'END'
frente acat <<< 'test string'
frenteecho 'test string' | cat
para tener la misma cantidad de expansiones realizadas por la concha en las cuerdas.$(seq $reps)
?Respuestas:
Primero, concentrémonos en el rendimiento. Ejecuté puntos de referencia para un programa ligeramente diferente en un procesador x86_64 en su mayoría inactivo que ejecuta Debian squeeze.
herestring.bash
, usando una herejía para pasar una línea de entrada:heredoc.bash
, usando un heredoc para pasar una línea de entrada:echo.bash
, usandoecho
y una tubería para pasar una línea de entrada:A modo de comparación, también cronometré los scripts bajo ATT ksh93 y bajo el guión (excepto
herestring.bash
porque el guión no tiene herejías).Aquí hay una mediana de tres veces:
Conclusiones:
echo
y una tubería es notable, pero no dramáticamente más rápida. (Tenga en cuenta que este es un programa de juguetes: en un programa real, la mayor parte del tiempo de procesamiento sería en lo que sea que latr
llamada representa aquí).Más allá del rendimiento, también hay claridad y portabilidad.
<<<
es una extensión ksh93 / bash / zsh que es menos conocida queecho … |
o<<
. No funciona en ksh88 / pdksh o en POSIX sh.El único lugar donde
<<<
podría decirse que es significativamente más claro es dentro de un heredoc:vs
(La mayoría de los depósitos no pueden hacer frente al cierre del paréntesis al final de la línea que contiene
<<EOF
).fuente
<<<
proviene derc
, y fue llevado por primera vez al mundo de shell de Bournezsh
.rc
no agregó una nueva línea final, sino todobash
,zsh
yksh93
AFAICT.rc
usa una tubería allí, whilebash
,zsh
yksh93
usa un archivo temporal como heredocs.<<<
aún menos útil.zsh
tiene una optimización=(<<<foo)
para crear efectivamente un archivo temporal que contiene "foo" que no implica bifurcar un proceso como lo=(echo foo)
haría.<<<
.Otra razón para usar heredocs (si no tenía suficiente) es que el eco puede fallar si la transmisión no se consume. Considere tener la
pipefail
opción bash ' :/bin/true
no consume su entrada estándar, peroecho yawn
completa sin embargo. Sin embargo, si se le pide a echo que imprima muchos datos, no se completará hasta que setrue
haya completado:141 es SIGPIPE (128 + 13) (se agrega 128 porque bash lo hace de acuerdo con bash (1):
Los heredocs no tienen este problema:
fuente
pipefail
predeterminado sea estar apagado!pipefail
en la parte superior de cada script. ¡Dame todos los errores!Una razón por la que es posible que desee usar echo es para ejercer cierto control sobre el carácter de nueva línea que se agrega al final de heredocs y hererestrings:
Tres caracteres
foo
tienen longitud 3:Sin embargo, una herejía de tres caracteres tiene cuatro caracteres:
Un heredoc de tres caracteres también:
El cuarto personaje es un
0x0a
personaje de nueva línea .De alguna manera, esto encaja mágicamente con la forma en que bash elimina estos caracteres de nueva línea al tomar la salida de un subconjunto:
Aquí hay un comando que devuelve cuatro caracteres:
foo
y\n
. El '\ n' se agrega por echo, siempre agrega un carácter de nueva línea a menos que especifique la-n
opción:Sin embargo, al asignar esto a una variable, se elimina la nueva línea final agregada por echo:
Entonces, si mezcla archivos y variables y los usa en los cálculos (por ejemplo, no puede usar heredocs o herestrings, ya que agregarán una nueva línea.
Si cambia la declaración if para leer
entonces la prueba pasa.
fuente