2117 Stimmen

Wie kann ich in der Bash über einen durch Variablen definierten Zahlenbereich iterieren?

Wie kann ich in Bash über einen Zahlenbereich iterieren, wenn der Bereich durch eine Variable vorgegeben ist?

Ich weiß, dass ich dies tun kann (in der Bash "Sequenzausdruck" genannt) Dokumentation ):

 for i in {1..5}; do echo $i; done

Das ergibt:

1
2
3
4
5

Doch wie kann ich einen der Endpunkte des Bereichs durch eine Variable ersetzen? Das funktioniert nicht:

END=5
for i in {1..$END}; do echo $i; done

Welche Drucke:

{1..5}

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.

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 wie 01, 02, 03, ..., 10 .

20voto

paxdiablo Punkte 809679

Dies funktioniert gut in bash :

END=5
i=1 ; while [[ $i -le $END ]] ; do
    echo $i
    ((i = i + 1))
done

15voto

theBuzzyCoder Punkte 2394

Es gibt viele Möglichkeiten, dies zu tun, aber die von mir bevorzugte ist die folgende

使用する seq

Synopse aus man seq

$ seq [-w] [-f format] [-s string] [-t string] [first [incr]] last

Syntax

Vollständiger Befehl
seq first incr last

  • first ist die Anfangsnummer in der Reihenfolge [ist optional, Standard:1]
  • incr ist Inkrement [ist optional, Standardwert:1]
  • last ist die letzte Nummer in der Folge

Exemple :

$ seq 1 2 10
1 3 5 7 9

Nur mit Vor- und Nachnamen:

$ seq 1 5
1 2 3 4 5

Nur mit Leisten:

$ seq 5
1 2 3 4 5

使用する {first..last..incr}

Hier sind Vor- und Nachname obligatorisch und incr ist optional

Nur Vor- und Nachname verwenden

$ echo {1..5}
1 2 3 4 5

Mit incr

$ echo {1..10..2}
1 3 5 7 9

Sie können dies auch für Zeichen wie die folgenden verwenden

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z

8voto

Adrian Frühwirth Punkte 38808

Ich weiß, dass es in dieser Frage um bash aber - nur um das festzuhalten - ksh93 ist schlauer und setzt sie wie erwartet um:

$ ksh -c 'i=5; for x in {1..$i}; do echo "$x"; done'
1
2
3
4
5
$ ksh -c 'echo $KSH_VERSION'
Version JM 93u+ 2012-02-29

$ bash -c 'i=5; for x in {1..$i}; do echo "$x"; done'
{1..5}

8voto

Jahid Punkte 19666

Dies ist ein anderer Weg:

end=5
for i in $(bash -c "echo {1..${end}}"); do echo $i; done

8voto

Zac B Punkte 3397

Wenn Sie so nah wie möglich an der Syntax des Klammerausdrucks bleiben wollen, probieren Sie die range Funktion von bash-tricks' range.bash .

Zum Beispiel bewirken alle folgenden Punkte genau dasselbe wie echo {1..10} :

source range.bash
one=1
ten=10

range {$one..$ten}
range $one $ten
range {1..$ten}
range {1..10}

Es versucht, die native Bash-Syntax mit so wenig "Problemen" wie möglich zu unterstützen: Es werden nicht nur Variablen unterstützt, sondern auch das oft unerwünschte Verhalten, dass ungültige Bereiche als Strings übergeben werden (z.B. for i in {1..a}; do echo $i; done ) wird ebenfalls verhindert.

Die anderen Antworten werden in den meisten Fällen funktionieren, aber sie haben alle mindestens einen der folgenden Nachteile:

  • Viele von ihnen verwenden Unterschalen die Schadensleistung y möglicherweise nicht möglich ist auf einigen Systemen.
  • Viele von ihnen sind auf externe Programme angewiesen. Auch seq ist eine Binärdatei, die installiert sein muss, um verwendet zu werden, die von der Bash geladen werden muss und die das erwartete Programm enthalten muss, damit sie in diesem Fall funktioniert. Ob allgegenwärtig oder nicht, man muss sich auf viel mehr verlassen als nur auf die Bash-Sprache selbst.
  • Lösungen, die nur native Bash-Funktionen verwenden, wie die von @ephemient, funktionieren nicht bei alphabetischen Bereichen, wie {a..z} ; Klammerausbau wird. Die Frage bezog sich auf Bereiche von Zahlen Das ist allerdings eine Spitzfindigkeit.
  • Die meisten von ihnen haben keine optische Ähnlichkeit mit dem {1..10} klammererweiterten Bereichssyntax, so dass Programme, die beides verwenden, etwas schwieriger zu lesen sein können.
  • Die Antwort von @bobbogo verwendet einige der bekannten Syntax, macht aber etwas Unerwartetes, wenn die $END Variable kein gültiges Bereichsende für die andere Seite des Bereichs ist. Wenn END=a tritt zum Beispiel kein Fehler auf und der wörtliche Wert {1..a} wird als Echo wiedergegeben. Dies ist auch das Standardverhalten der Bash - es ist nur oft unerwartet.

Haftungsausschluss: Ich bin der Autor des verlinkten Codes.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X