Dieser Befehl hängt davon ab, dass die Shell 5000 Argumente generiert und diese übergibt, printfdie 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 trnur 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 trVersion erreichte durchschnittlich etwa 0,012 Sekunden - und die trVersion ü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 forSchleife 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 printfnatü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 %.0Zeichenfolgen 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 ddwie 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=1die obigen Zeilen hinzufügen und von dort aus beliebige Zeichenfolgen pro Zeile mit pasteund einfügen. /dev/nullIn diesem Fall können Sie jedoch auch Folgendes verwenden , wenn es für Sie verfügbar ist:
yes 'output string forever'
Hier noch einige ddBeispiele:
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 . ddsucht 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 ddgeskilled Verhalten s‘des Schreibens aus mindestens einen vollständigen Nullblock im Fall eines Lesefehlers , wenn noerrorund syncConversions 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.
tcshoderzsh,repeat 5000 printf Hist leichter zu verstehen. Mitperl:print "H" x 5000(beachten Sie, dass das{1..5000}ein zsh Operator inspiriertperl‚s1..5000ein und später von ksh93 und bash kopiert)