Perintah itu tergantung pada shell yang menghasilkan 5000 argumen, dan meneruskannya printf
yang 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 tr
itu 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 tr
versi datang sekitar rata-rata total 0,012 detik - dan tr
versi 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 for
loop 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 printf
untuk zeropad angka yang berubah-ubah, tentu saja, seperti:
printf %05000d
Saya melakukan keduanya tanpa argumen karena untuk setiap argumen yang ditentukan dalam printf
format 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 %.0
memanjang 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 dd
seperti:
printf \\0| dd bs=64k conv=sync
... dan dd
dengan 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=1
di atas dan dari sana bisa menyuntikkan string sewenang-wenang per baris dengan paste
dan /dev/null
- tetapi dalam hal itu, jika tersedia untuk Anda, Anda mungkin sebaiknya menggunakan:
yes 'output string forever'
Berikut ini beberapa dd
contoh lagi:
dd bs=5000 seek=1 if=/dev/null of=./H.txt
... yang menciptakan (atau memotong) sebuah \0NUL
file yang diisi dengan direktori saat ini bernama H.txt ukuran 5000 bytes. dd
mencari 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 dd
perilaku spesifik menulis setidaknya satu nol blok penuh jika terjadi kesalahan baca ketika noerror
dan sync
konversi ditentukan (dan - tanpa count=
- kemungkinan akan berlangsung lebih lama dari yang Anda inginkan) , dan dengan sengaja mengarahkan ulang deskriptor file writeonly dd
di stdin.
tcsh
atauzsh
,repeat 5000 printf H
lebih mudah dimengerti. Denganperl
:print "H" x 5000
(catatan bahwa{1..5000}
adalah operator zsh terinspirasi olehperl
's1..5000
satu dan kemudian disalin oleh ksh93 dan bash)