Dieser Befehl hängt davon ab, dass die Shell 5000 Argumente generiert und diese übergibt, printf
die dann ignoriert werden. Während es ziemlich schnell zu sein scheint - und relativ zu einigen Dingen ist - muss die Shell dennoch alle diese Zeichenfolgen als Argumente generieren (und sie abgrenzen) und so weiter.
Neben der Tatsache, dass die generierten Hs erst gedruckt werden können, wenn die Shell zum ersten Mal auf 5000 iteriert, kostet dieser Befehl im Speicher auch alles, was zum Speichern und Abgrenzen der numerischen Zeichenfolgenargumente printf
plus Hs erforderlich ist . Genauso einfach können Sie Folgendes tun:
printf %05000s|tr \ H
... was eine Zeichenfolge von 5000 Leerzeichen erzeugt - die normalerweise nur ein einzelnes Byte pro sind und deren Abgrenzung nichts kostet, weil sie nicht abgegrenzt sind. Einige Tests zeigen, dass sich die Kosten für die Gabel und das Rohr, die für tr
nur 5000 Bytes erforderlich sind, auch in diesem Fall lohnen, und dies fast immer dann, wenn die Zahlen höher werden.
Ich rannte...
time bash -c 'printf H%.0s {1..5000}' >/dev/null
...und...
time bash -c 'printf %05000s|tr \ H' >/dev/null
Jeweils etwa fünfmal pro Stück (hier nichts Wissenschaftliches - nur anekdotisch) und die Klammererweiterungsversion hatten eine durchschnittliche Gesamtverarbeitungszeit von etwas mehr als 0,02 Sekunden, aber die tr
Version erreichte durchschnittlich etwa 0,012 Sekunden - und die tr
Version übertraf sie jedes Mal. Ich kann nicht sagen, dass ich überrascht bin - es {brace expansion}
ist eine nützliche interaktive Shell-Kurzform, aber normalerweise eine ziemlich verschwenderische Sache, wenn es um Skripte geht. Die übliche Form:
for i in {[num]..[num]}; do ...
... wenn Sie darüber nachdenken, sind es wirklich zwei for
Schleifen - die erste ist intern und impliziert, dass die Shell eine Schleife ausführen muss, um diese Iteratoren zu generieren, bevor sie alle gespeichert und für Ihre for
Schleife erneut iteriert werden . Solche Dinge werden normalerweise besser gemacht als:
iterator=$start
until [ "$((iterator+=interval))" -gt "$end" ]; do ...
... weil Sie nur sehr wenige Werte speichern und diese im Laufe der Zeit überschreiben und die Iteration ausführen, während Sie die Iterables generieren.
Wie bei der zuvor erwähnten Leerzeichenauffüllung können Sie printf
natürlich auch eine beliebige Anzahl von Ziffern auf Null setzen , z. B.:
printf %05000d
Ich mache beides ohne Argumente, weil für jedes Argument, das in der Formatzeichenfolge angegeben ist printf
, wenn ein Argument nicht gefunden wird, die Nullzeichenfolge verwendet wird - die als Null für ein Ziffernargument oder als leere Zeichenfolge für eine Zeichenfolge interpretiert wird.
Dies ist die andere (und meiner Meinung nach effizientere) Seite der Medaille im Vergleich zu dem Befehl in der Frage - während es möglich ist, nichts von etwas zu bekommen, wie Sie es tun, wenn Sie printf %.0
Zeichenfolgen für jedes Argument verlängern, so ist es auch es ist möglich, etwas aus dem Nichts zu bekommen.
Noch schneller für große Mengen generierter Bytes, die Sie dd
wie folgt verwenden können :
printf \\0| dd bs=64k conv=sync
... und w / reguläre Dateien dd
‚s seek=[num]
Argument kann zu größeren Vorteil verwendet werden. Sie können 64.000 Zeilenumbrüche anstelle von Nullen erhalten, wenn Sie ,unblock cbs=1
die obigen Zeilen hinzufügen und von dort aus beliebige Zeichenfolgen pro Zeile mit paste
und einfügen. /dev/null
In diesem Fall können Sie jedoch auch Folgendes verwenden , wenn es für Sie verfügbar ist:
yes 'output string forever'
Hier noch einige dd
Beispiele:
dd bs=5000 seek=1 if=/dev/null of=./H.txt
... die eine gefüllte Datei im aktuellen Verzeichnis mit dem Namen H.txt mit einer Größe von 5000 Byte erstellt (oder abschneidet)\0NUL
. dd
sucht direkt zum Offset und NUL-Fills alle dahinter.
<&1 dd bs=5000 conv=sync,noerror count=1 | tr \\0 H >./H.txt
... wodurch eine Datei mit demselben Namen und derselben Größe erstellt wird, die jedoch mit H-Zeichen gefüllt ist. Es nutzt dd
geskilled Verhalten s‘des Schreibens aus mindestens einen vollständigen Nullblock im Fall eines Lesefehlers , wenn noerror
und sync
Conversions angegeben werden (und - ohne count=
- wahrscheinlich weitergehen würde mehr als man sich wünschen könnte) , und absichtlich Umleitungen ein schreibgeschützter Dateideskriptor bei dd
's stdin.
tcsh
oderzsh
,repeat 5000 printf H
ist leichter zu verstehen. Mitperl
:print "H" x 5000
(beachten Sie, dass das{1..5000}
ein zsh Operator inspiriertperl
‚s1..5000
ein und später von ksh93 und bash kopiert)