Ця команда залежить від оболонки, що генерує 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=
- швидше за все , триватиме довше , ніж ви могли б хотіти) , і навмисно переадресовує дескриптор файлу тільки для запису на dd
stdin.
tcsh
абоzsh
,repeat 5000 printf H
простіше зрозуміти. Зperl
:print "H" x 5000
(зауважте, що{1..5000}
це zsh-оператор, натхненний oneperl
''s1..5000
та пізніше скопійований ksh93 та bash)