Ich habe ein paar der hier vorgestellten Ideen kombiniert und die Leistung gemessen.
TL;DR Takeaways:
seq
y {..}
sind wirklich schnell
for
y while
Schleifen sind langsam
$( )
ist langsam
for (( ; ; ))
Schleifen sind langsamer
$(( ))
ist noch langsamer
- Besorgnis über N Zahlen im Speicher (seq oder {..}) ist albern (zumindest bis zu 1 Million.)
Diese sind nicht Schlussfolgerungen . Um daraus Schlüsse zu ziehen, müssten Sie sich den C-Code ansehen, der hinter jedem dieser Programme steht. Hier geht es eher darum, wie wir jeden dieser Mechanismen für Schleifen im Code verwenden. Die meisten Einzeloperationen sind nahe genug an der gleichen Geschwindigkeit, dass es in den meisten Fällen keine Rolle spielen wird. Aber ein Mechanismus wie for (( i=1; i<=1000000; i++ ))
ist eine Vielzahl von Operationen, wie Sie visuell sehen können. Es sind auch viele weitere Operationen pro Schleife als Sie von for i in $(seq 1 1000000)
. Und das ist für Sie vielleicht nicht offensichtlich, weshalb Tests wie dieser so wertvoll sind.
Demos
# show that seq is fast
$ time (seq 1 1000000 | wc)
1000000 1000000 6888894
real 0m0.227s
user 0m0.239s
sys 0m0.008s
# show that {..} is fast
$ time (echo {1..1000000} | wc)
1 1000000 6888896
real 0m1.778s
user 0m1.735s
sys 0m0.072s
# Show that for loops (even with a : noop) are slow
$ time (for i in {1..1000000} ; do :; done | wc)
0 0 0
real 0m3.642s
user 0m3.582s
sys 0m0.057s
# show that echo is slow
$ time (for i in {1..1000000} ; do echo $i; done | wc)
1000000 1000000 6888896
real 0m7.480s
user 0m6.803s
sys 0m2.580s
$ time (for i in $(seq 1 1000000) ; do echo $i; done | wc)
1000000 1000000 6888894
real 0m7.029s
user 0m6.335s
sys 0m2.666s
# show that C-style for loops are slower
$ time (for (( i=1; i<=1000000; i++ )) ; do echo $i; done | wc)
1000000 1000000 6888896
real 0m12.391s
user 0m11.069s
sys 0m3.437s
# show that arithmetic expansion is even slower
$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; i=$(($i+1)); done | wc)
1000000 1000000 6888896
real 0m19.696s
user 0m18.017s
sys 0m3.806s
$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $i; ((i=i+1)); done | wc)
1000000 1000000 6888896
real 0m18.629s
user 0m16.843s
sys 0m3.936s
$ time (i=1; e=1000000; while [ $i -le $e ]; do echo $((i++)); done | wc)
1000000 1000000 6888896
real 0m17.012s
user 0m15.319s
sys 0m3.906s
# even a noop is slow
$ time (i=1; e=1000000; while [ $((i++)) -le $e ]; do :; done | wc)
0 0 0
real 0m12.679s
user 0m11.658s
sys 0m1.004s
41 Stimmen
Hallo zusammen, die Informationen und Tipps, die ich hier gelesen habe, sind alle sehr hilfreich. Ich denke, es ist am besten, die Verwendung von seq zu vermeiden. Der Grund dafür ist, dass einige Skripte portabel sein müssen und auf einer Vielzahl von Unix-Systemen laufen müssen, auf denen einige Befehle möglicherweise nicht vorhanden sind. Nur um ein Beispiel zu nennen: seq ist auf FreeBSD-Systemen standardmäßig nicht vorhanden.
2 Stimmen
Verwandte Themen: bash for-Schleife: ein Bereich von Zahlen y unix.stackexchange.com - Ist es in der Bash möglich, eine Integer-Variable in der Schleifensteuerung einer for-Schleife zu verwenden?
12 Stimmen
Ich weiß nicht mehr, seit welcher Version der Bash genau, aber dieser Befehl unterstützt auch abschließende Nullen. Was manchmal wirklich hilfreich ist. Befehl
for i in {01..10}; do echo $i; done
würde Zahlen ergeben wie01, 02, 03, ..., 10
.4 Stimmen
Für diejenigen, die wie ich nur über den Bereich der Indizes einer Array wäre die Bash-Methode:
myarray=('a' 'b' 'c'); for i in ${!myarray[@]}; do echo $i; done
(beachten Sie das Ausrufezeichen). Sie ist spezifischer als die ursprüngliche Frage, könnte aber hilfreich sein. Siehe Bash-Parameter-Erweiterungen1 Stimmen
Die Klammererweiterung wird auch für Ausdrücke verwendet wie
{jpg,png,gif}
was hier nicht direkt angesprochen wird, obwohl die Antwort identisch sein wird. Siehe Klammererweiterung mit Variable? [Duplikat] die als Duplikat dieses Dokuments gekennzeichnet ist.0 Stimmen
Freebsd scheint zu haben
seq
jetzt "in diesen Tagen" FWIW...0 Stimmen
Intenté
for i in {1..${END}}; do echo ${i}; done
. Dies funktioniert in der Terminal-Befehlszeile, aber nicht in einem SHELL-Skript, was mich verwirrt.1 Stimmen
@PhoenixMu, Sie können das Shell-Skript mit bash yourscript.sh statt mit sh yourscript.sh ausführen
0 Stimmen
@XinNiu Stimmt;