С tcshили zsh, repeat 5000 printf Hпроще понять. С perl: print "H" x 5000(обратите внимание, что {1..5000}это оператор zsh, вдохновленный оператором perls, 1..5000а затем скопированным ksh93 и bash)
Стефан Шазелас
да, это работает, но использует много ресурсов для большего повторения, следуйте советам Стефана
Шазеласа
1
я бы сделал эту командуyes H|head -5000|tr -d '\012'
Skaperen
dd if=/dev/zero bs=5000 count=1 | tr '\0' H
Кодзиро
@Skaepren:yes H| head -n 2500| tr \\n H
mikeserv
Ответы:
20
Эта команда зависит от оболочки, генерирующей 5000 аргументов и передающей их, printfкоторая затем игнорирует их. Хотя это может показаться довольно быстрым - и относительно некоторых вещей - оболочка все равно должна генерировать все эти строки как аргументы (и разделять их) и так далее.
Помимо того факта, что сгенерированные H не могут быть напечатаны до тех пор, пока оболочка не выполнит итерацию до 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 раз за штуку (ничего научного здесь - только анекдотичный), и версия расширения фигурной скобки в среднем trзанимала чуть более 0,02 секунды в общем времени обработки, но версия в среднем занимала около 0,012 секунды - и trверсия побеждала каждый раз. Я не могу сказать, что удивлен - {brace expansion}это полезная функция сокращенной интерактивной оболочки, но обычно она довольно расточительна, когда речь идет о любом виде сценариев. Распространенная форма:
for i in{[num]..[num]};do...
... когда вы думаете об этом, на самом деле это дваfor цикла - первый является внутренним и подразумевает, что оболочка должна каким-то образом выполнить цикл для генерации этих итераторов, прежде чем сохранять их все и повторять их снова для вашего forцикла. Такие вещи обычно лучше сделать как:
... потому что вы сохраняете только очень немного значений и перезаписываете их по мере выполнения, а также выполняете итерацию, пока генерируете итерации.
В любом случае, как и в случае с пробелом, упомянутым выше, вы можете также использовать printfдля нумерации произвольное количество цифр, например:
printf %05000d
Я делаю оба без аргументов, потому что для каждого аргумента, указанного в printfстроке формата, когда аргумент не найден, используется пустая строка, которая интерпретируется как ноль для аргумента с цифрой или пустая строка для строки.
Это другая (и, на мой взгляд, более эффективная) сторона медали по сравнению с командой, о которой идет речь, - хотя можно получить что-то от чего-либо, как вы, когда вы printf %.0длина строк для каждого аргумента, также можно получить что-то из ничего.
Еще быстрее для большого количества сгенерированных байтов, которые вы можете использовать ddкак:
printf \\0| dd bs=64k conv=sync
... и аргумент ddс обычными файлами seek=[num]может быть использован для большего преимущества. Вы можете получить 64 тыс. Новых строк, а не нулей, если добавите ,unblock cbs=1к вышеупомянутому и оттуда можете вставлять произвольные строки в строку с помощью pasteи /dev/null- но в этом случае, если это доступно для вас, вы также можете использовать:
yes 'output string forever'
Вот еще несколько ddпримеров:
dd bs=5000 seek=1if=/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специфицированного поведения по записи по крайней мере одного полного нулевого блока в случае ошибки чтения, когда указаны noerrorи syncпреобразования (и - без count=- скорее всего, будет длиться дольше, чем вы хотели) , и намеренно перенаправляет файловый дескриптор, доступный только для записи, в ddstdin.
%.0sОзначает преобразовать аргумент как строку , с точностью нуля. Согласно man 3 printf, значение точности в таком случае дает
[...] the maximum number of characters to be printed from a
string for s and S conversions.
следовательно, когда точность равна нулю, строковый аргумент вообще не печатается. Однако H(который является частью спецификатора формата) печатается столько раз, сколько есть аргументов, поскольку согласно printfразделуman bash
The format is reused as necessary to consume all of the argu‐
ments.If the format requires more arguments than are supplied,
the extra format specifications behave as if a zero value or
null string, as appropriate, had been supplied.
В этом случае %.0sвсегда печатается один экземпляр символа (ов), предшествующий ему, в этом случае H. Когда вы используете {1..5000}, оболочка расширяет его и становится:
printf 'H%.0s'1234...5000> H.txt
то есть команда printf теперь имеет 5000 аргументов, и для каждого аргумента вы получите один H. Они не должны быть последовательными или числовыми:
printf 'H%.0s' a bc fg 1234
печатает HHHHH- т.е. количество аргументов, 5 в этом случае.
Обратите внимание, что эллипсы в 1-м примере выше не вставляются буквально, они там указывают последовательность или диапазон.
tcsh
илиzsh
,repeat 5000 printf H
проще понять. Сperl
:print "H" x 5000
(обратите внимание, что{1..5000}
это оператор zsh, вдохновленный операторомperl
s,1..5000
а затем скопированным ksh93 и bash)yes H|head -5000|tr -d '\012'
dd if=/dev/zero bs=5000 count=1 | tr '\0' H
yes H| head -n 2500| tr \\n H
Ответы:
Эта команда зависит от оболочки, генерирующей 5000 аргументов и передающей их,
printf
которая затем игнорирует их. Хотя это может показаться довольно быстрым - и относительно некоторых вещей - оболочка все равно должна генерировать все эти строки как аргументы (и разделять их) и так далее.Помимо того факта, что сгенерированные H не могут быть напечатаны до тех пор, пока оболочка не выполнит итерацию до 5000, эта команда также стоит в памяти все, что требуется для хранения и ограничения числовых строковых аргументов
printf
плюс Hs. Так же просто, как вы можете сделать:... который генерирует строку из 5000 пробелов, которые, по крайней мере, обычно занимают всего один байт и ничего не стоят для разделения, поскольку они не разделены. Несколько тестов показывают, что даже для всего лишь 5000 байт стоимость вилки и трубы, требуемой для
tr
нее, оправдывает себя даже в этом случае, и почти всегда это происходит, когда числа становятся выше.Я побежал ...
...и...
Каждый примерно 5 раз за штуку (ничего научного здесь - только анекдотичный), и версия расширения фигурной скобки в среднем
tr
занимала чуть более 0,02 секунды в общем времени обработки, но версия в среднем занимала около 0,012 секунды - иtr
версия побеждала каждый раз. Я не могу сказать, что удивлен -{brace expansion}
это полезная функция сокращенной интерактивной оболочки, но обычно она довольно расточительна, когда речь идет о любом виде сценариев. Распространенная форма:... когда вы думаете об этом, на самом деле это два
for
цикла - первый является внутренним и подразумевает, что оболочка должна каким-то образом выполнить цикл для генерации этих итераторов, прежде чем сохранять их все и повторять их снова для вашегоfor
цикла. Такие вещи обычно лучше сделать как:... потому что вы сохраняете только очень немного значений и перезаписываете их по мере выполнения, а также выполняете итерацию, пока генерируете итерации.
В любом случае, как и в случае с пробелом, упомянутым выше, вы можете также использовать
printf
для нумерации произвольное количество цифр, например:Я делаю оба без аргументов, потому что для каждого аргумента, указанного в
printf
строке формата, когда аргумент не найден, используется пустая строка, которая интерпретируется как ноль для аргумента с цифрой или пустая строка для строки.Это другая (и, на мой взгляд, более эффективная) сторона медали по сравнению с командой, о которой идет речь, - хотя можно получить что-то от чего-либо, как вы, когда вы
printf %.0
длина строк для каждого аргумента, также можно получить что-то из ничего.Еще быстрее для большого количества сгенерированных байтов, которые вы можете использовать
dd
как:... и аргумент
dd
с обычными файламиseek=[num]
может быть использован для большего преимущества. Вы можете получить 64 тыс. Новых строк, а не нулей, если добавите,unblock cbs=1
к вышеупомянутому и оттуда можете вставлять произвольные строки в строку с помощьюpaste
и/dev/null
- но в этом случае, если это доступно для вас, вы также можете использовать:Вот еще несколько
dd
примеров:... который создает (или усекает) в
\0NUL
заполненный файл в текущем каталоге с именем H.txt от размера 5000 байт.dd
стремится прямо к смещению и заполняет все NUL за ним.... который создает файл с тем же именем и размером, но заполненный символами W / H. Он использует преимущества
dd
специфицированного поведения по записи по крайней мере одного полного нулевого блока в случае ошибки чтения, когда указаныnoerror
иsync
преобразования (и - безcount=
- скорее всего, будет длиться дольше, чем вы хотели) , и намеренно перенаправляет файловый дескриптор, доступный только для записи, вdd
stdin.источник
%.0s
Означает преобразовать аргумент как строку , с точностью нуля. Согласноman 3 printf
, значение точности в таком случае даетследовательно, когда точность равна нулю, строковый аргумент вообще не печатается. Однако
H
(который является частью спецификатора формата) печатается столько раз, сколько есть аргументов, поскольку согласноprintf
разделуman bash
источник
В этом случае
%.0s
всегда печатается один экземпляр символа (ов), предшествующий ему, в этом случае H. Когда вы используете {1..5000}, оболочка расширяет его и становится:то есть команда printf теперь имеет 5000 аргументов, и для каждого аргумента вы получите один H. Они не должны быть последовательными или числовыми:
печатает
HHHHH
- т.е. количество аргументов, 5 в этом случае.Обратите внимание, что эллипсы в 1-м примере выше не вставляются буквально, они там указывают последовательность или диапазон.
источник