Até agora, o Uso inútil do cat
prêmio é muito conhecido, e também há uma menção ao Uso inútil deecho
(não relevante para esta pergunta). Gostaria de saber se deve haver um "Uso Inútil echo
no Prêmio Bash": a tubulação parece ser muito mais lenta que os heredocs e herestrings, de acordo com algumas medidas altamente não 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
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
Redirecionamento
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
Em geral, heredocs e herestrings têm aproximadamente a mesma velocidade (este é apenas um conjunto de dados de vários testes) enquanto o redirecionamento é consistentemente mais do que 50% mais lento. Estou entendendo mal algo ou isso poderia ser usado como regra geral para comandos que leem a entrada padrão no Bash?
seq
" prêmio ;-)cat <<END
vs.cat <<< "test string"
vs.echo "test string" | cat
oucat <<'END'
vs.cat <<< 'test string'
vs.echo 'test string' | cat
para ter a mesma quantidade de expansões executadas pelo shell nas seqüências.$(seq $reps)
?Respostas:
Primeiro, vamos nos concentrar no desempenho. Eu executei benchmarks para um programa um pouco diferente em um processador x86_64 normalmente ocioso executando o Debian squeeze.
herestring.bash
, usando um herestring para passar uma linha de entrada:heredoc.bash
, usando um heredoc para passar uma linha de entrada:echo.bash
, usingecho
e um pipe para passar uma linha de entrada:Para comparação, também cronometrei os scripts no ATT ksh93 e no dash (exceto
herestring.bash
porque o dash não possui legendas).Aqui estão a mediana de três vezes:
Conclusões:
echo
e um tubo é visivelmente, mas não dramaticamente mais rápido. (Lembre-se de que este é um programa de brinquedos: em um programa real, a maior parte do tempo de processamento seria em qualquer que seja atr
chamada aqui.)Além do desempenho, também há clareza e portabilidade.
<<<
é uma extensão ksh93 / bash / zsh que é menos conhecida queecho … |
ou<<
. Não funciona no ksh88 / pdksh ou no POSIX sh.O único lugar onde
<<<
é discutivelmente significativamente mais claro é dentro de um heredoc:vs
(A maioria das conchas não consegue lidar com o fechamento dos parênteses no final da linha que contém
<<EOF
.)fonte
<<<
vemrc
e foi trazido pela primeira vez ao mundo de conchas tipo Bournezsh
.rc
não adicionou uma nova linha à direita, mas todasbash
,zsh
eksh93
faz AFAICT.rc
usa um pipe lá, whilebash
,zsh
eksh93
usa um arquivo temporário como para heredocs.<<<
ainda menos útil.zsh
há uma otimização=(<<<foo)
para criar efetivamente um arquivo temporário que contém "foo", que não envolve a bifurcação de um processo como=(echo foo)
faria.<<<
.Outro motivo para usar heredocs (se você não tiver o suficiente) é que o eco poderá falhar se o fluxo não for consumido. Considere ter a
pipefail
opção bash ' :/bin/true
não consome sua entrada padrão, mas éecho yawn
concluído mesmo assim. No entanto, se for solicitado que o eco imprima muitos dados, ele não será concluído até quetrue
seja concluído:141 é SIGPIPE (128 + 13) (128 sendo adicionado porque o bash faz isso de acordo com o bash (1):
Heredocs não têm esse problema:
fonte
pipefail
padrão seja desligado!pipefail
no topo de cada script. Me dê todos os erros!Um motivo pelo qual você pode querer usar echo é exercer algum controle sobre o caractere de nova linha que é adicionado ao final de heredocs e herestrings:
Três caracteres
foo
tem comprimento 3:No entanto, um caractere de três caracteres possui quatro caracteres:
Um heredoc de três caracteres também:
O quarto caractere é um
0x0a
caractere de nova linha .De alguma forma, isso se encaixa magicamente com a maneira como o bash remove esses caracteres de nova linha ao obter a saída de um sub-shell:
Aqui está um comando que retorna quatro caracteres:
foo
e\n
. O '\ n' é adicionado pelo eco, ele sempre adiciona um caractere de nova linha, a menos que você especifique a-n
opção:No entanto, atribuindo isso a uma variável, a nova linha à direita adicionada pelo eco é removida:
Portanto, se você combinar arquivos e variáveis e usá-los em cálculos (por exemplo, não poderá usar heredocs ou herestrings, pois eles adicionarão uma nova linha.
Se você alterar a instrução if para ler
então o teste passa.
fonte