Pada saat Penggunaan Useless of cat
Award sangat terkenal, dan ada juga yang menyebutkan Penggunaan Useless ofecho
(tidak relevan untuk pertanyaan ini). Saya bertanya-tanya apakah harus ada "Penggunaan yang Tidak Berguna echo
dalam Bash Award": Perpipaan tampaknya jauh lebih lambat daripada heredocs dan herestrings menurut beberapa pengukuran yang sangat tidak ilmiah:
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
Pengalihan
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
Secara umum, heredocs dan herestrings memiliki kecepatan yang sama (ini hanya satu set data dari beberapa tes) sementara pengalihan secara konsisten lebih dari 50% lebih lambat. Apakah saya salah memahami sesuatu, atau dapatkah ini digunakan sebagai aturan umum untuk perintah yang membaca input standar di Bash?
seq
penghargaan " penggunaan yang tidak berguna " ;-)cat <<END
vscat <<< "test string"
vsecho "test string" | cat
ataucat <<'END'
vscat <<< 'test string'
vsecho 'test string' | cat
untuk memiliki jumlah ekspansi yang sama yang dilakukan oleh shell pada string.$(seq $reps)
?Jawaban:
Pertama, mari kita berkonsentrasi pada kinerja. Saya menjalankan tolok ukur untuk program yang sedikit berbeda pada prosesor x86_64 yang sebagian besar tidak bekerja menjalankan pemerasan Debian.
herestring.bash
, menggunakan herestring untuk memberikan masukan:heredoc.bash
, menggunakan heredoc untuk memberikan masukan:echo.bash
, menggunakanecho
dan pipa untuk melewati jalur input:Sebagai perbandingan, saya juga mengatur waktu skrip di bawah ATT ksh93 dan di bawah tanda hubung (kecuali untuk
herestring.bash
, karena tanda hubung tidak memiliki herestrings).Inilah median tiga kali:
Kesimpulan:
echo
dan sebuah pipa terasa, tetapi tidak secara dramatis lebih cepat. (Ingatlah bahwa ini adalah program mainan: dalam program nyata, sebagian besar waktu pemrosesan akan sesuai dengan apa puntr
panggilannya di sini.)Selain kinerja, ada juga kejelasan dan portabilitas.
<<<
adalah ekstensi ksh93 / bash / zsh yang kurang dikenalecho … |
atau<<
. Ini tidak berfungsi di ksh88 / pdksh atau di POSIX sh.Satu-satunya tempat di mana
<<<
secara signifikan lebih jelas adalah di dalam heredoc:vs.
(Kebanyakan shell tidak dapat mengatasi penutupan tanda kurung di akhir baris yang berisi
<<EOF
.)sumber
<<<
berasal darirc
, dan pertama kali dibawa ke dunia shell seperti Bourne olehzsh
.rc
tidak menambahkan baris baru, tetapi semuanyabash
,zsh
danksh93
lakukan AFAICT.rc
menggunakan pipa di sana, sementarabash
,zsh
danksh93
menggunakan file sementara seperti untuk heredocs.<<<
bahkan kurang bermanfaat.zsh
memiliki pengoptimalan=(<<<foo)
untuk secara efektif membuat file temp yang berisi "foo" yang tidak melibatkan proses forking seperti yang=(echo foo)
akan terjadi.<<<
.Alasan lain untuk menggunakan heredocs (jika Anda tidak memiliki cukup) adalah bahwa gema dapat gagal jika aliran tidak dikonsumsi. Pertimbangkan memiliki
pipefail
opsi bash ' :/bin/true
tidak mengkonsumsi input standarnya, tetapiecho yawn
tetap melengkapi. Namun, jika gema diminta untuk mencetak banyak data, itu tidak akan selesai sampai setelahtrue
selesai:141 adalah SIGPIPE (128 + 13) (128 ditambahkan karena bash melakukannya sesuai dengan bash (1):
Heredocs tidak memiliki masalah ini:
sumber
pipefail
defaultnya tidak aktif!pipefail
di bagian atas setiap skrip. Beri aku semua kesalahan!Salah satu alasan Anda mungkin ingin menggunakan gema adalah untuk mengontrol beberapa karakter baris baru yang ditambahkan ke akhir heredocs dan herestrings:
Tiga karakter
foo
memiliki panjang 3:Namun, threecharacter herestring adalah empat karakter:
Heredoc tiga karakter juga:
Karakter keempat adalah
0x0a
karakter baris baru .Entah bagaimana ini secara ajaib cocok dengan cara bash menghapus karakter-karakter baris baru ini ketika mengambil output dari sub-shell:
Berikut adalah perintah yang mengembalikan empat karakter:
foo
dan\n
. '\ N' ditambahkan oleh gema, itu selalu menambahkan karakter baris baru kecuali jika Anda menentukan-n
opsi:Namun, dengan menetapkan ini ke variabel, baris baru yang ditambahkan oleh gema dihapus:
Jadi jika Anda mencampur file dan variabel dan menggunakannya dalam perhitungan (misalnya, Anda tidak dapat menggunakan heredocs atau herestrings, karena mereka akan menambahkan baris baru.
Jika Anda mengubah pernyataan if untuk dibaca
kemudian tes berlalu.
sumber