Ця команда залежить від оболонки, що генерує 5000 аргументів, і передаючи їх, printfпісля чого їх ігнорує. Хоча це може здатися досить швидким - і відносно деяких речей - оболонка все одно повинна генерувати всі ці рядки як аргументи (і розмежовувати їх) тощо.
Окрім того, що згенеровані Hs не можуть бути надруковані, поки оболонка спочатку не ітералізує 5000, ця команда також коштує в пам'яті все, що потрібно для зберігання та розмежування числових аргументів до printf плюс Hs. Так само просто:
printf %05000s|tr \ H
... що генерує рядок з 5000 пробілів - які, принаймні, зазвичай є лише одним байтом на кожний і нічого не коштують для розмежування, оскільки вони не обмежені. Кілька тестів показують, що навіть на цілих 5000 байт вартість вилки та труби, необхідних для trцього, варта навіть у цьому випадку, і це майже завжди, коли цифри зростають.
Я побіг ...
time bash -c 'printf H%.0s {1..5000}' >/dev/null
... і ...
time bash -c 'printf %05000s|tr \ H' >/dev/null
Кожна приблизно 5 разів за шматок (нічого наукового тут - лише анекдотичне) і версія розширення брекетів в середньому за трохи перевищувала 0,02 секунди, але trверсія в середньому склала приблизно 0,012 секунди - і trверсія обіграла її кожного разу. Я не можу сказати, що я здивований - {brace expansion}це корисна функція інтерактивної стенограми оболонки, але зазвичай це досить марно, що стосується будь-якого сценарію. Загальна форма:
for i in {[num]..[num]}; do ...
... коли ви задумаєтесь, це справді дві for петлі - перша є внутрішньою і має на увазі те, що оболонка повинна певним чином циклічно створювати ці ітератори, перш ніж зберегти їх усіх і повторити повторне повторення для вашого forциклу. Зазвичай такі речі краще робити:
iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...
... тому що ви зберігаєте лише дуже мало значень і перезаписуєте їх під час переходу, а також виконуючи ітерацію, створюючи ітерабелі.
У будь-якому випадку, як і пробіл, згаданий раніше, ви також можете використовувати printfдля нульової панелі довільну кількість цифр, звичайно, як:
printf %05000d
Я обидва без аргументів, тому що для кожного аргументу, зазначеного в printfрядку формату ', коли аргумент не знайдено, використовується нульова рядок - що інтерпретується як нуль для цифрового аргументу або порожня рядок для рядка.
Це інша (і, на мій погляд, - більш ефективна) сторона монети в порівнянні з командою у питанні - в той час як ви можете отримати нічого з чогось, як ви робите, коли ви printf %.0довжини рядків для кожного аргументу, так само є можна щось отримати з нічого.
Швидше все-таки для великої кількості генерованих байтів, якими ви можете користуватися dd:
printf \\0| dd bs=64k conv=sync
... і ж / звичайні файли dd«и seek=[num]можна використовувати аргумент для більшої вигоди. Ви можете отримати 64k нових рядків, а не нульових значень, якщо ви додасте ,unblock cbs=1до вищезазначеного і звідти зможете вставити довільні рядки на рядок із pasteі /dev/null- але в такому випадку, якщо він вам доступний, ви можете також використовувати:
yes 'output string forever'
Ось ще кілька ddприкладів:
dd bs=5000 seek=1 if=/dev/null of=./H.txt
... який створює (або усікає) в \0NULзаповнений файл в поточному каталозі з іменем H.txt від розмірі 5000 байт. ddшукає прямо до зміщення і NUL заповнює все за ним.
<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt
... який створює файл з такою ж назвою та розміром, але заповнений w / H символів. Він використовує ddбілд поведінку «s виписувати по крайней мере , один повний нуль-блок в разі помилки читання , коли noerrorі syncперетворення вказані (і - без count=- швидше за все , триватиме довше , ніж ви могли б хотіти) , і навмисно переадресовує дескриптор файлу тільки для запису на ddstdin.
tcshабоzsh,repeat 5000 printf Hпростіше зрозуміти. Зperl:print "H" x 5000(зауважте, що{1..5000}це zsh-оператор, натхненний oneperl''s1..5000та пізніше скопійований ksh93 та bash)