我发现以下命令在Linux中重复一个字符:
printf 'H%.0s' {1..5000} > H.txt
例如,我想H
重复5000
一次。这%.0s
是什么意思?
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
我发现以下命令在Linux中重复一个字符:
printf 'H%.0s' {1..5000} > H.txt
例如,我想H
重复5000
一次。这%.0s
是什么意思?
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
Answers:
该命令取决于shell生成5000个参数,然后将其传递给它们printf
,然后忽略它们。尽管它看起来非常快-并且相对于某些事情而言-shell仍必须将所有这些字符串生成为args (并对其进行定界),依此类推。
除了生成的Hs在外壳程序第一次迭代到5000之前无法打印的事实之外,该命令还消耗了存储和将数字字符串参数定界并printf
加上 Hs 所需的全部内存。就像您可以做到的一样:
printf %05000s|tr \ H
...这将生成一个由5000个空格组成的字符串-至少每个空格通常只有一个字节,并且无需花费任何定界费用,因为它们没有定界。一些测试表明,即使在只有5000个字节的tr
情况下,即使在这种情况下,fork和所需的管道的成本也是值得的,而且几乎总是在数字增加时。
我跑了
time bash -c 'printf H%.0s {1..5000}' >/dev/null
...和...
time bash -c 'printf %05000s|tr \ H' >/dev/null
每次大约5次(这里没什么科学意义-只是轶事),而括号扩展版本的平均总处理时间为.02秒多一点,但该tr
版本平均平均大约为.012秒- tr
击败了它每次。我不能说我很惊讶-这{brace expansion}
是一个有用的交互式Shell速记功能,但是在涉及任何类型的脚本时,这通常是一件相当浪费的事情。常见形式:
for i in {[num]..[num]}; do ...
...当您考虑时,实际上是两个 for
循环-第一个是内部循环,这意味着外壳程序必须以某种方式循环以生成那些迭代器,然后再保存所有迭代器并为for
循环再次对其进行迭代。这样的事情通常更好地完成,例如:
iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...
...因为您只存储了很少的值,并且在生成可迭代对象时进行迭代以及执行过程中都将其覆盖。
无论如何,就像前面提到的空格填充一样,您当然也可以使用printf
零填充任意数量的数字,例如:
printf %05000d
我都没有参数,因为对于printf
找不到格式参数的格式字符串中指定的每个参数,都使用null字符串-对于数字参数,它解释为零,对于字符串,则解释为空字符串。
与问题中的命令相比,这是硬币的另一面(在我看来,这是更有效的一面),但是,当您printf %.0
为每个参数加长字符串时,可能无法从中得到任何东西,所以也是有可能一事无成。
仍然可以更快地使用大量生成的字节,dd
例如:
printf \\0| dd bs=64k conv=sync
...和带有常规文件dd
的seek=[num]
参数可以用于更大的优势。如果添加,unblock cbs=1
到上面,则可以获得64k换行符,而不是null ,然后可以使用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
...这将创建一个相同名称和大小的文件,但带有H字符。它利用了dd
'spec'的行为,即在指定了noerror
和sync
转换时(如果没有count=
-进行的时间可能比您想要的更长),在发生读取错误的情况下,至少写出一个完整的空块,并且有意地进行重定向位于dd
stdin 的只写文件描述符。
该%.0s
机构的说法转换为字符串,具有精确的零。根据man 3 printf
,在这种情况下的精度值给出
[ ... ] the maximum number of characters to be printed from a
string for s and S conversions.
因此,当精度为零时,根本不会输出string参数。然而,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.
tcsh
或zsh
,repeat 5000 printf H
更容易理解。随着perl
:print "H" x 5000
(注意,{1..5000}
是灵感的zsh运营商perl
的1..5000
一个,后来被ksh93的和bash复制)