Perintah itu tergantung pada shell yang menghasilkan 5000 argumen, dan meneruskannya printfyang kemudian mengabaikannya. Meskipun mungkin terlihat cukup cepat - dan relatif untuk beberapa hal - shell masih harus menghasilkan semua string sebagai args (dan membatasi mereka) dan seterusnya.
Selain fakta bahwa Hs yang dihasilkan tidak dapat dicetak sampai shell pertama kali beralih ke 5000, perintah itu juga menghabiskan semua memori yang diperlukan untuk menyimpan dan membatasi argumen string numerik menjadi printf ditambah Hs. Sederhananya yang dapat Anda lakukan:
printf %05000s|tr \ H
... yang menghasilkan string 5000 ruang - yang, setidaknya, biasanya hanya satu byte per dan tidak ada biaya untuk membatasi karena tidak dibatasi. Beberapa tes menunjukkan bahwa bahkan untuk sedikitnya 5.000 byte biaya garpu dan pipa yang diperlukan untuk tritu layak bahkan dalam kasus ini, dan hampir selalu adalah ketika jumlahnya semakin tinggi.
Saya berlari ...
time bash -c 'printf H%.0s {1..5000}' >/dev/null
...dan...
time bash -c 'printf %05000s|tr \ H' >/dev/null
Masing-masing sekitar 5 kali sepotong (tidak ada yang ilmiah di sini - hanya anekdotal) dan versi ekspansi brace rata-rata sedikit lebih dari 0,02 detik dalam total waktu pemrosesan, tetapi trversi datang sekitar rata-rata total 0,012 detik - dan trversi mengalahkannya setiap saat. Saya tidak bisa mengatakan saya terkejut - {brace expansion}adalah fitur steno shell interaktif yang berguna, tetapi biasanya hal yang agak boros untuk dilakukan di mana pun jenis scripting yang bersangkutan. Bentuk umum:
for i in {[num]..[num]}; do ...
... ketika Anda memikirkannya, benar-benar dua for loop - yang pertama adalah internal dan tersirat dalam bahwa shell harus diulang dengan cara tertentu untuk menghasilkan iterator sebelum menyimpan semuanya dan mengulanginya lagi untuk forloop Anda . Hal-hal seperti itu biasanya lebih baik dilakukan seperti:
iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...
... karena Anda menyimpan nilai yang sangat sedikit dan menimpa mereka saat Anda pergi serta melakukan iterasi saat Anda menghasilkan iterables.
Pokoknya, seperti ruang yang disebutkan sebelumnya, Anda juga dapat menggunakan printfuntuk zeropad angka yang berubah-ubah, tentu saja, seperti:
printf %05000d
Saya melakukan keduanya tanpa argumen karena untuk setiap argumen yang ditentukan dalam printfformat string ketika sebuah argumen tidak ditemukan, string nol digunakan - yang ditafsirkan sebagai nol untuk argumen digit atau string kosong untuk string.
Ini adalah sisi lain (dan - menurut saya - lebih efisien) dari sisi koin jika dibandingkan dengan perintah dalam pertanyaan - sementara dimungkinkan untuk tidak mendapatkan apa pun dari sesuatu seperti yang Anda lakukan saat Anda printf %.0memanjang string untuk setiap argumen, demikian juga mungkin untuk mendapatkan sesuatu dari ketiadaan.
Masih lebih cepat untuk sejumlah besar byte yang dihasilkan yang dapat Anda gunakan ddseperti:
printf \\0| dd bs=64k conv=sync
... dan dddengan seek=[num]argumen file biasa dapat digunakan untuk keuntungan yang lebih besar. Anda bisa mendapatkan 64k baris baru daripada nol jika Anda menambahkan ,unblock cbs=1di atas dan dari sana bisa menyuntikkan string sewenang-wenang per baris dengan pastedan /dev/null- tetapi dalam hal itu, jika tersedia untuk Anda, Anda mungkin sebaiknya menggunakan:
yes 'output string forever'
Berikut ini beberapa ddcontoh lagi:
dd bs=5000 seek=1 if=/dev/null of=./H.txt
... yang menciptakan (atau memotong) sebuah \0NULfile yang diisi dengan direktori saat ini bernama H.txt ukuran 5000 bytes. ddmencari langsung ke offset dan NUL-mengisi semua di belakangnya.
<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt
... yang membuat file dengan nama dan ukuran yang sama tetapi diisi dengan karakter w. Ini mengambil keuntungan dari ddperilaku spesifik menulis setidaknya satu nol blok penuh jika terjadi kesalahan baca ketika noerrordan synckonversi ditentukan (dan - tanpa count=- kemungkinan akan berlangsung lebih lama dari yang Anda inginkan) , dan dengan sengaja mengarahkan ulang deskriptor file writeonly dddi stdin.
tcshatauzsh,repeat 5000 printf Hlebih mudah dimengerti. Denganperl:print "H" x 5000(catatan bahwa{1..5000}adalah operator zsh terinspirasi olehperl's1..5000satu dan kemudian disalin oleh ksh93 dan bash)