BASH: Beschreibung von for-, while-, Until-Schleifen und Anwendungsbeispiele. Endlose While-Schleife in einem BASH-Skript WHILE- und UNTIL-Schleifen

💖 Gefällt es dir? Teilen Sie den Link mit Ihren Freunden

Autor: Paul Cobbaut
Veröffentlichungsdatum: 16. Oktober 2014
Übersetzung: A. Panin
Übersetzungsdatum: 21. Dezember 2014

Kapitel 22. Schleifen in Skripten

Testbefehl

Mit dem Testbefehl können Sie feststellen, ob ein Ausdruck wahr oder falsch ist. Beginnen wir damit, zu testen, ob der ganzzahlige Wert 10 größer als der ganzzahlige Wert 55 ist. $ test 10 -gt 55 ; Echo $? 1$

Der Testbefehl gibt 1 zurück, wenn der Ausdruck falsch ist. Und wie Sie im folgenden Beispiel sehen werden, gibt der Testbefehl 0 zurück, wenn der Ausdruck „true“ ergibt. $ test 56 -gt 55 ; Echo $? 0 $

Wenn Sie lieber mit den Zeichenfolgen „true“ und „false“ arbeiten, können Sie den Testbefehl wie unten gezeigt verwenden. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || echo false false

Der Testbefehl kann auch ersetzt werden eckige Klammern, sodass die Befehle aus dem Beispiel unten den Befehlen aus dem Beispiel oben völlig ähnlich sind. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || echo false false

Nachfolgend finden Sie Beispiele für die Implementierung einiger Prüfungen. Eine Übersicht finden Sie auf der Man-Test-Seite Zusatzfunktionen Durchführung diverser Kontrollen. [ -d foo ] Existiert das Verzeichnis foo? [ -e bar ] Existiert die bar-Datei? [ "/etc" = $PWD ] Entspricht /etc dem Wert von $PWD? [ $1 != "secret" ] Unterscheidet sich der Wert des ersten Skriptparameters von der geheimen Zeichenfolge? [ 55 -lt $bar ] Ist der ganzzahlige Wert 55 kleiner als der Wert von $bar? [ $foo -ge 1000 ] Ist der Wert von $foo größer oder gleich dem ganzzahligen Wert 1000? ["ABC"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar lesbare Datei? [foo -nt bar] Ist foo neuer als bar? [ -o nounset ] Ist die Nounset-Shell-Option aktiviert?

Prüfoperatoren können mit entsprechenden Operatoren kombiniert werden logische Operationen„UND“ und „ODER“. paul@RHEL4b:~$ [ 66 -gt 55 -a 66 -lt 500 ] && echo true || echo false true paul@RHEL4b:~$ [ 66 -gt 55 -a 660 -lt 500 ] && echo true || echo false false paul@RHEL4b:~$ [ 66 -gt 55 -o 660 -lt 500 ] && echo true || Echo falsch wahr

Bedingter Sprung wenn dann sonst

Das if then else-Konstrukt soll eine Codeoption auswählen. Wenn eine bestimmte Bedingung erfüllt ist, wird ein Teil des Codes ausgeführt, andernfalls wird ein anderer Code ausgeführt. Das folgende Beispiel prüft, ob eine Datei vorhanden ist. Wenn die Annahme, dass die Datei vorhanden ist, bestätigt wird, wird eine entsprechende Meldung angezeigt. #!/bin/bash if [ -f isit.txt ] then echo die Datei isit.txt existiert! sonst Echo-Datei isit.txt nicht gefunden! fi

Wenn wir diesen Skriptcode in einer Datei namens „choice“ speichern, kann er auf die gleiche Weise ausgeführt werden. $ ./choice Datei isit.txt nicht gefunden! $ touch isit.txt $ ./choice Datei isit.txt existiert! $

Bedingter Sprung wenn dann elif

Mit der elif-Anweisung können Sie eine neue if-Anweisung in einen else-Block einfügen. Nachfolgend finden Sie ein einfaches Beispiel für einen solchen Eintrag. #!/bin/bash count=42 if [ $count -eq 42 ] then echo „42 ist ein gültiger Wert.“ elif [ $count -gt 42 ] dann echo „Zu viele.“ sonst echo „Nicht genug.“ fi

for-Schleife

Das folgende Beispiel zeigt die Syntax einer klassischen for-Schleife in der Bash-Shell. denn ich in 1 2 4 mache echo $i done

Ein Beispiel für die Verwendung einer for-Schleife in Kombination mit einem Inline-Shell-Aufruf. #!/bin/ksh für Zähler in „seq 1 20“ führt Echozählung von 1 bis 20 durch, aktueller Wert $counter Sleep 1 fertig

Ein dem oben vorgestellten völlig ähnliches Skript kann ohne Verwendung einer eingebetteten Befehls-Shell erstellt werden, indem die Bash-Shell-Deklaration für einen Wertebereich (von Wert bis Wert) verwendet wird. #!/bin/bash für Zähler in (1..20) führt Echozählung von 1 bis 20 durch, aktueller Wert $counter Sleep 1 fertig

Diese for-Schleife verwendet einen Mechanismus zum Durchsuchen von Dateien nach Mustern (implementiert als Teil des Befehlserweiterungsmechanismus). Wenn die oben genannten Anweisungen direkt in veröffentlicht werden Befehlszeile, es wird ähnlich funktionieren. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ für Datei in *.ksh ; mach cp $file $file.backup ; erledigt kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

while-Schleife

Unten finden Sie ein einfaches Beispiel für die Verwendung einer While-Schleife. ich=100; while [ $i -ge 0 ] ; do echo Countdown von 100 auf 0, aktueller Wert $i; lass ich--; Erledigt

Endlosschleifen können mithilfe von while true- oder while:-Deklarationen implementiert werden, wobei das Symbol: das Äquivalent der fehlenden Operation in der Korn-Shell und Bash ist. #!/bin/ksh # Endlosschleife while: do echo hello sleep 1 done

Bis-Schleife

Unten finden Sie ein einfaches Beispiel für die Verwendung einer Until-Schleife. sei i=100; bis [ $i -le 0 ] ; do echo Countdown von 100 auf 1, aktueller Wert $i; lass ich--; Erledigt

Übung: Tests und Schleifen in Skripten

3. Entwickeln Sie ein Skript, das eine While-Schleife verwendet, um von 3 bis 7 zu zählen.

4. Entwickeln Sie ein Skript, das eine Bis-Schleife verwendet, um von 8 auf 4 herunterzuzählen.

5. Entwickeln Sie ein Skript, das Dateien mit der Erweiterung .txt im aktuellen Verzeichnis zählt.

6. Verwenden Sie eine if-Anweisung im generierten Skript, um korrekte Bedienung wenn im aktuellen Verzeichnis keine Dateien mit der Erweiterung .txt vorhanden sind.

Das richtige Vorgehen zur Erledigung einer praktischen Aufgabe: Prüfungen und Schleifen in Skripten

1. Entwickeln Sie ein Skript, das eine for-Schleife verwendet, um von 3 bis 7 zu zählen.

#!/bin/bash for i in 3 4 5 6 7 do echo Zählen von 3 bis 7, aktueller Wert $i fertig

2. Entwickeln Sie ein Skript, das eine for-Schleife verwendet, um von 1 bis 17000 zu zählen.

Die Bash-Shell unterstützt for-Schleifen, mit denen Sie Wertesequenzen durchlaufen können. Hier ist die Grundstruktur solcher Schleifen:

Führen Sie für die Variable in der Liste den Befehl „Done“ aus
In jeder Iteration der Schleife wird die Variable var auf den nächsten Wert geschrieben Liste. Beim ersten Durchlauf der Schleife wird daher der erste Wert aus der Liste verwendet. Im zweiten - dem zweiten und so weiter - bis die Schleife das letzte Element erreicht.

Iterieren über einfache Werte

Das vielleicht einfachste Beispiel einer for-Schleife in Bash-Skripten ist das Durchlaufen einer Liste einfacher Werte:

#!/bin/bash für var im ersten zweiten dritten vierten fünften do echo Das $var-Element ist fertig
Die Ergebnisse dieses Skripts werden unten angezeigt. Sie können deutlich erkennen, dass die Variable $var nacheinander Elemente aus der Liste enthält. Dies geschieht, bis der Zyklus den letzten von ihnen erreicht.


Einfache for-Schleife

Bitte beachten Sie, dass die Variable $var beim Verlassen der Schleife ihren Wert behält, ihr Inhalt geändert werden kann und Sie im Allgemeinen wie jede andere Variable mit ihr arbeiten können.

Iterieren über komplexe Werte

Die zum Initialisieren der for-Schleife verwendete Liste kann nicht nur einfache Zeichenfolgen enthalten, die aus einem Wort bestehen, sondern auch ganze Phrasen, die mehrere Wörter und Satzzeichen enthalten. Es könnte zum Beispiel so aussehen:

#!/bin/bash für var in erster „der zweiten“ „der dritten“ „Ich mache es“ do echo „Das ist: $var“ fertig
Dies geschieht, nachdem diese Schleife die Liste durchlaufen hat. Wie Sie sehen, ist das Ergebnis durchaus zu erwarten.


Iterieren über komplexe Werte
TNW-CUS-FMP – Aktionscode für 10 % Rabatt auf unsere Dienste, verfügbar zur Aktivierung innerhalb von 7 Tagen“

Initialisieren einer Schleife mit einer Liste, die aus den Ergebnissen des Befehls erhalten wird

Eine andere Möglichkeit, eine for-Schleife zu initialisieren, besteht darin, ihr eine Liste zu übergeben, die das Ergebnis eines Befehls ist. Hier wird die Befehlsersetzung verwendet, um sie auszuführen und die Ergebnisse ihrer Arbeit zu erhalten.

#!/bin/bash file="myfile" für var in $(cat $file) do echo " $var" done
In diesem Beispiel wird der Befehl cat verwendet, der den Inhalt einer Datei liest. Die resultierende Werteliste wird an die Schleife übergeben und auf dem Bildschirm angezeigt. Bitte beachten Sie, dass die Datei, auf die wir zugreifen, eine Liste von Wörtern enthält, die durch Zeilenumbrüche getrennt sind; es werden keine Leerzeichen verwendet.


Eine Schleife, die den Inhalt einer Datei durchläuft

Hierbei ist zu berücksichtigen, dass ein solcher Ansatz, wenn eine zeilenweise Datenverarbeitung erwartet wird, für eine Datei mit komplexerer Struktur, deren Zeilen mehrere durch Leerzeichen getrennte Wörter enthalten können, nicht funktioniert. Die Schleife verarbeitet einzelne Wörter, keine Zeilen.

Was ist, wenn dies überhaupt nicht das ist, was Sie brauchen?

Feldtrennzeichen

Der Grund für die oben genannte Funktion ist das Besondere Umgebungsvariable, das IFS (Internal Field Separator) heißt und es Ihnen ermöglicht, Feldtrennzeichen anzugeben. Standardmäßig betrachtet die Bash-Shell die folgenden Zeichen als Feldtrennzeichen:
  • Raum
  • Tabulatorzeichen
  • Zeilenvorschubzeichen
Wenn Bash in den Daten auf eines dieser Zeichen stößt, geht es davon aus, dass ihm der nächste unabhängige Wert in der Liste vorangestellt ist.

Um das Problem zu beheben, können Sie die IFS-Umgebungsvariable vorübergehend ändern. So machen Sie es in einem Bash-Skript, vorausgesetzt, Sie benötigen nur eine neue Zeile als Feldtrennzeichen:

IFS=$"\n"
Sobald Sie diesen Befehl zu Ihrem Bash-Skript hinzufügen, funktioniert er wie erwartet, ignoriert Leerzeichen und Tabulatoren und behandelt nur Zeilenumbrüche als Feldtrennzeichen.

#!/bin/bash file="/etc/passwd" IFS=$"\n" für var in $(cat $file) echo " $var" done
Wenn dieses Skript ausgeführt wird, gibt es genau das aus, was von ihm verlangt wird, und gewährt bei jeder Iteration der Schleife Zugriff auf die nächste in die Datei geschriebene Zeile.


Zeile für Zeile Durchlauf einer Datei in einer for-Schleife

Trennzeichen können auch andere Zeichen sein. Oben haben wir beispielsweise den Inhalt der Datei /etc/passwd angezeigt. Benutzerdaten in Zeilen werden durch Doppelpunkte getrennt. Wenn Sie solche Zeichenfolgen in einer Schleife verarbeiten müssen, kann IFS wie folgt konfiguriert werden:

Durchsuchen von Dateien, die in einem Verzeichnis enthalten sind

Eine der häufigsten Anwendungen von for-Schleifen in Bash-Skripten besteht darin, Dateien in einem Verzeichnis zu durchlaufen und diese Dateien zu verarbeiten.

So listen Sie beispielsweise Dateien und Ordner auf:

#!/bin/bash für Datei in /home/likegeeks/* do if [ -d „$file“ ] then echo „$file is adirectory“ elif [ -f „$file“ ] then echo „$file is a Datei" fi fertig
Wenn Sie das vorherige Material dieser Artikelserie verstanden haben, sollten Sie die Struktur des Wenn-Dann-Konstrukts verstehen und wissen, wie Sie eine Datei von einem Ordner unterscheiden. Wenn Sie Schwierigkeiten haben, den obigen Code zu verstehen, lesen Sie dieses Material noch einmal.

Dies ist die Ausgabe des Skripts.


Den Inhalt eines Ordners anzeigen

Beachten Sie, wie wir die Schleife initialisieren, nämlich den Platzhalter „*“ am Ende der Ordneradresse. Dieses Symbol kann man sich als Platzhalter vorstellen und bedeutet: „alle Dateien mit beliebigen Namen“. Damit können Sie die automatische Ersetzung von Dateinamen organisieren, die dem Muster entsprechen.

Beim Testen einer Bedingung in einer if-Anweisung setzen wir den Variablennamen in Anführungszeichen. Dies geschieht, weil der Datei- oder Ordnername Leerzeichen enthalten kann.

C-Stil für Schleifen

Wenn Sie mit der Programmiersprache C vertraut sind, kommt Ihnen die Syntax zur Beschreibung von Bash-For-Schleifen möglicherweise seltsam vor, da Sie es offensichtlich gewohnt sind, Schleifen auf diese Weise zu beschreiben:

Für (i = 0; i< 10; i++) { printf("number is %d\n", i); }
In Bash-Skripten können Sie for-Schleifen verwenden, deren Beschreibung den Schleifen im C-Stil sehr ähnlich sieht, obwohl es einige Unterschiede gibt. Das Zyklusdiagramm mit diesem Ansatz sieht folgendermaßen aus:

For ((Anfangswert der Variable; Bedingung für Schleifenende; Änderung der Variable))
In Bash kann es so geschrieben werden:

Für ((a = 1; a< 10; a++))
Hier ist ein funktionierendes Beispiel:

#!/bin/bash für ((i=1; i<= 10; i++)) do echo "number is $i" done
Dieser Code gibt eine Liste mit Zahlen von 1 bis 10 aus.

Looping im C-Stil

while-Schleife

Das for-Konstrukt ist nicht die einzige Möglichkeit, Schleifen in Bash-Skripten zu organisieren. Sie können hier auch while-Schleifen verwenden. In einer solchen Schleife können Sie einen Befehl zum Überprüfen einer bestimmten Bedingung angeben und den Schleifenkörper ausführen, bis die getestete Bedingung Null oder ein Signal für den erfolgreichen Abschluss einer bestimmten Operation zurückgibt. Wenn die Schleifenbedingung einen Wert ungleich Null zurückgibt, was einen Fehler bedeutet, wird die Schleife gestoppt.

Hier ist ein Diagramm der Organisation von While-Schleifen
while Bedingungsüberprüfungsbefehl
Tun
andere Mannschaften
Erledigt

Schauen wir uns ein Beispielskript mit einer Schleife wie dieser an:

#!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] done
Am Schleifeneingang wird geprüft, ob die Variable $var1 größer als Null ist. Wenn ja, wird der Hauptteil der Schleife ausgeführt, in dem eins vom Wert der Variablen subtrahiert wird. Dies geschieht in jeder Iteration und wir geben den Wert der Variablen auf der Konsole aus, bevor er geändert wird. Sobald $var1 den Wert 0 erreicht, stoppt die Schleife.

Ergebnis der while-Schleife

Wenn Sie die Variable $var1 nicht ändern, endet das Skript in einer Endlosschleife.

Verschachtelte Schleifen

Sie können beliebige Befehle im Schleifenkörper verwenden, einschließlich des Startens anderer Schleifen. Solche Konstruktionen nennt man verschachtelte Schleifen:

#!/bin/bash für ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Nachfolgend finden Sie die Ausgabe dieses Skripts. Wie man sieht, wird zuerst die erste Iteration der äußeren Schleife ausgeführt, dann drei Iterationen der inneren, nach deren Abschluss kommt wieder die äußere Schleife ins Spiel, dann wieder die innere.

Verschachtelte Schleifen

Dateiinhalte verarbeiten

Am häufigsten werden verschachtelte Schleifen zur Verarbeitung von Dateien verwendet. Die äußere Schleife durchläuft also die Zeilen der Datei und die innere Schleife arbeitet bereits mit jeder Zeile. So sieht beispielsweise die Verarbeitung der Datei /etc/passwd aus:

#!/bin/bash IFS=$"\n" für Eintrag in $(cat /etc/passwd) do echo "Values ​​​​in $entry –" IFS=: for value in $entry do echo " $value" done Erledigt
Dieses Skript enthält zwei Schleifen. Der erste durchläuft die Zeilen und verwendet dabei das Zeilenumbruchzeichen als Trennzeichen. Der interne ist damit beschäftigt, Zeichenfolgen zu analysieren, deren Felder durch Doppelpunkte getrennt sind.

Dateidatenverarbeitung

Dieser Ansatz kann bei der Verarbeitung von CSV-Dateien oder ähnlichen Dateien verwendet werden, indem das Trennzeichen nach Bedarf in die IFS-Umgebungsvariable geschrieben wird.

Zyklusmanagement

Möglicherweise müssen Sie nach dem Eintritt in die Schleife diese stoppen, wenn die Schleifenvariable einen bestimmten Wert erreicht, der nicht der ursprünglich festgelegten Bedingung zum Beenden der Schleife entspricht. Muss in einer solchen Situation auf den normalen Abschluss des Zyklus gewartet werden? Natürlich nicht, und in solchen Fällen sind die folgenden beiden Befehle hilfreich:
  • brechen
  • weitermachen

break-Befehl

Mit diesem Befehl können Sie die Ausführung einer Schleife unterbrechen. Es kann sowohl für for- als auch für while-Schleifen verwendet werden:

#!/bin/bash für var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Number: $var1" done
Eine solche Schleife durchläuft unter normalen Bedingungen die gesamte Werteliste aus der Liste. In unserem Fall wird die Ausführung jedoch unterbrochen, wenn die Variable $var1 gleich 5 ist.

Eine for-Schleife vorzeitig verlassen

Hier ist das Gleiche, aber für die while-Schleife:

#!/bin/bash var1=1 while [ $var1 -lt 10 ] do if [ $var1 -eq 5 ] then break fi echo "Iteration: $var1" var1=$(($var1 + 1)) done
Der Befehl break, der ausgeführt wird, wenn $var1 5 erreicht, unterbricht die Schleife. Die Konsole zeigt dasselbe an wie im vorherigen Beispiel.

Befehl fortsetzen

Wenn dieser Befehl im Hauptteil der Schleife angetroffen wird, endet die aktuelle Iteration vorzeitig und die nächste beginnt, ohne die Schleife zu verlassen. Schauen wir uns den continue-Befehl in einer for-Schleife an:

#!/bin/bash für ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Wenn die Bedingung innerhalb der Schleife erfüllt ist, d. h. wenn $var1 größer als 5 und kleiner als 10 ist, führt die Shell den Befehl continue aus. Dies führt dazu, dass die verbleibenden Befehle im Schleifenkörper übersprungen werden und mit der nächsten Iteration fortgefahren wird.

Der continue-Befehl in einer for-Schleife

Die Ausgabe wird in einer Schleife verarbeitet

Die Datenausgabe einer Schleife kann verarbeitet werden, indem die Ausgabe entweder umgeleitet oder an eine Pipeline übergeben wird. Dies geschieht durch das Hinzufügen von Ausgabeverarbeitungsbefehlen nach der done-Anweisung.

Anstatt beispielsweise auf dem Bildschirm anzuzeigen, was in einer Schleife ausgegeben wird, können Sie alles in eine Datei schreiben oder an eine andere Stelle übergeben:

#!/bin/bash für ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo „fertig.“
Die Shell erstellt die Datei myfile.txt und leitet die Ausgabe der for-Anweisung in diese Datei um. Öffnen wir die Datei und stellen wir sicher, dass sie genau das enthält, was wir erwarten.

Schleifenausgabe in eine Datei umleiten

Beispiel: Suche nach ausführbaren Dateien

Lassen Sie uns das verwenden, was wir bereits behandelt haben, und etwas Nützliches schreiben. Wenn Sie beispielsweise herausfinden möchten, welche ausführbaren Dateien auf dem System verfügbar sind, können Sie alle in der Umgebungsvariablen PATH aufgezeichneten Ordner scannen. Wir verfügen bereits über das gesamte Arsenal an Werkzeugen, die wir dafür benötigen, wir müssen es nur noch zusammenfügen:

#!/bin/bash IFS=: für Ordner in $PATH echo „$folder:“ für Datei in $folder/* do if [ -x $file ] then echo „ $file“ fi done done
Dieses kleine und einfache Skript ermöglichte es uns, eine Liste der ausführbaren Dateien abzurufen, die in Ordnern von PATH gespeichert sind.

Suche nach ausführbaren Dateien in Ordnern anhand der PATH-Variablen

Ergebnisse

Heute haben wir über for- und while-Schleifen in Bash-Skripten gesprochen, wie man sie ausführt und wie man sie verwaltet. Jetzt wissen Sie, wie Sie Zeichenfolgen mit unterschiedlichen Trennzeichen in Schleifen verarbeiten, wie Sie die Datenausgabe in Schleifen in Dateien umleiten und wie Sie den Inhalt von Verzeichnissen anzeigen und analysieren.

Wenn wir davon ausgehen, dass Sie ein Entwickler von Bash-Skripten sind, der nur das kennt, was im ersten Teil dieser Artikelserie und im zweiten Teil gesagt wird, dann können Sie bereits etwas Nützliches schreiben. Vor uns liegt der dritte Teil. Nachdem Sie ihn verstanden haben, erfahren Sie, wie Sie Parameter und Befehlszeilenschalter an Bash-Skripte übergeben und was Sie damit machen.

Eine kurze Beschreibung der Unterschiede zwischen den Schleifentypen:

for – führt eine Aktion aus, solange es auszuführende Objekte gibt (z. B. das Lesen eines Streams aus stdin, einer Datei oder einer Funktion);
while – führt die Aktion aus, bis Zustand ist wahr;
bis - wird so lange ausgeführt wie Zustand wird nicht wahr werden, d.h. im Moment ist es falsch.

FOR-Schleife

Betrachten wir diese Version des Skripts mit einer Schleife:

$ cat loop.sh #!/bin/bash für Variable in „ls -1“ echo „$variable“ ausführen fertig

Die Syntax ist sehr einfach und wird im Beispiel ganz anschaulich dargestellt:

for (Schleife starten) Variable (eine Variable deklarieren, für die wir Aktionen ausführen) in (einen Fluss an die Schleife senden) `ls -1` (Befehl, der ausgeführt und an die Variable $variable übergeben werden soll). Do und done sind der „Körper“ der Schleife, in dem die Hauptaktionen an den empfangenen Daten ausgeführt werden, und echo „$variable“ ist die tatsächliche Aktion, die von der Schleife ausgeführt wird.

Jetzt ändern wir das Beispiel ein wenig und verwenden anstelle der expliziten Angabe des Befehls die zweite Variable:

$ cat loop.sh #!/bin/bash ls=`ls -1` für Variable in $ls do echo „$variable“ done

Jetzt wird der Befehl ls -1 in einer separaten Variablen übergeben, wodurch Sie flexibler mit der Schleife arbeiten können. Anstelle einer Variablen in einer Schleife können Sie auch eine Funktion verwenden:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) für Variable in „lsl“ echo „$variable“ ausführen fertig

Die Hauptbedingung der for-Schleife besteht darin, dass sie ausgeführt wird, solange der an sie übergebene Befehl Objekte für die Aktion enthält. Basierend auf dem obigen Beispiel – solange ls -1 Dateien zum Anzeigen hat – übergibt die Schleife diese an eine Variable und führt den „Schleifenkörper“ aus. Sobald die Liste der Dateien im Verzeichnis endet, wird die Schleife ausgeführt.

Machen wir das Beispiel etwas komplizierter.

Das Verzeichnis enthält eine Liste von Dateien:

$ ls -1 file1 file2 file3 file4 file5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

Wir müssen nur diejenigen auswählen, die das Wort „“ nicht enthalten. NEIN«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` für Variable in $lsl do echo „$variable“ | grep -v "no" done $ ./loop.sh file1 file2 file3 file4 file5 loop.sh

Sie können auch bedingte Ausdrücke in einer Schleife verwenden ( Bedingte Ausdrücke) […] um Bedingungen zu überprüfen und die break-Anweisung, um die Schleife zu unterbrechen, wenn die Bedingung ausgelöst wird.

Betrachten Sie dieses Beispiel:

$ cat loop.sh #!/bin/bash lsl=`ls -1` für Variable in $lsl do if [ $variable != "loop.sh" ] then echo "$variable" | grep -v "no" sonst break fi fertig

Die Schleife wird fortgesetzt, bis die Datei loop.sh gefunden wird. Sobald die Ausführung der Schleife diese Datei erreicht, wird die Schleife durch den Befehl break unterbrochen:

$ ./loop.sh Datei1 Datei2 Datei3 Datei4 Datei5

Ein weiteres Beispiel ist die Verwendung arithmetischer Operationen unmittelbar vor der Ausführung des Schleifenkörpers:

$ cat loop.sh #!/bin/bash for ((count=1; count<11; count++)) do echo "$count" done

Hier legen wir drei Steuerbefehle fest – count=1, eine Steuerbedingung – während count kleiner als 11 ist, und einen auszuführenden Befehl – ​​count +1:

WHILE- und UNTIL-Schleifen

Ein einfaches Beispiel, das deutlich zeigt, wie die while-Schleife funktioniert:

$ cat loop.sh #!/bin/bash count=0 while [ $count -lt 10 ] do ((count++)) echo $count done

Wir setzen die Variable $count auf Null und führen dann die while-Schleife mit der Bedingung aus: „Solange $count kleiner als zehn ist, führen Sie die Schleife aus.“ Im Hauptteil der Schleife führen wir aus Postfix-Inkrement+1 auf die Variable $count und das Ergebnis wird auf stdout ausgegeben.

Ausführungsergebnis:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10

Sobald der Wert der Variablen $count 10 wurde, wurde die Schleife gestoppt.

Ein gutes Beispiel für eine „Endlosschleife“, die zeigt, wie while funktioniert:

$ cat loop.sh #!/bin/bash count=10 while [ 1 = 1 ] do ((count++)) echo $count done $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^C

Die Until-Schleife funktioniert ähnlich, jedoch in umgekehrter Richtung:

$ cat loop.sh #!/bin/bash count=0 bis [ $count -gt 10 ] do ((count++)) echo $count done

Hier legen wir eine ähnliche Bedingung fest, aber statt „solange die Variable kleiner als 10 ist“ geben wir an „bis die Variable größer als 10 wird“. Ausführungsergebnis:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11

Wenn das obige Beispiel einer „Endlosschleife“ mit „bis“ ausgeführt wird, wird im Gegensatz zu „while“ nichts ausgegeben:

$ cat loop.sh #!/bin/bash count=10 Until [ 1 = 1 ] do ((count++)) echo $count done $ ./loop.sh $

Als " Zustand"ursprünglich" WAHR„—Der Schleifenkörper wird nicht ausgeführt.

Genau wie in der for-Schleife können Sie Funktionen in while und Until verwenden. Zum Beispiel eine Schleife aus einem realen Skript, das den Serverstatus überprüft Kater(PID wird vom System übernommen SLES, kann in anderen Systemen abweichen), eine leicht vereinfachte Version:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) while check_tomcat_status do if [ -n "$ RUN“ ] dann printf „WARNUNG: Tomcat läuft immer noch mit PID $RUN.“ else printf „Tomcat hat angehalten, geht weiter...nn“ break fi done

Ausführungsergebnis:

$ ./loop.sh WARNUNG: Tomcat läuft immer noch mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch läuft mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch mit PID 14435 26548.WARNUNG: Tomcat läuft immer noch mit PID 14435

Vollversion:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) while check_tomcat_status; do if [ -n "$RUN" ] then printf "WARNUNG: Tomcat läuft immer noch mit PID $RUN. Stoppen? " Antwort "Stoppt Tomcat..." "Installation wird fortgesetzt..." && $CATALINA_HOME/bin/shutdown . sh 2&>1 /dev/null || break sleep 2 if [ -n "$RUN" ] then printf „Tomcat läuft noch. Kill it?“ Antwort „Tomcat wird getötet…“ „Installation wird fortgesetzt...n“ && kill $RUN || break sleep 2 fi else printf „Tomcat gestoppt, fährt fort...nn“ break fi fertig

Die Antwortfunktion wurde im Artikel beschrieben, hier kommt jedoch eine leicht verbesserte Version zum Einsatz:

Answer () ( beim Lesen der Antwort; echo case $response in |) printf "$1n" return 0 break ;; |) printf „$2n“ return 1 break ;; *) printf „Bitte geben Sie Y(ja) oder N(nein) ein!“ esac done )

Hier war es möglich, sowohl while als auch Until zu verwenden – jedoch keine for-Schleife, da for einmal funktioniert hätte (die PID erhalten und beendet).

Schleifen sind beim Schreiben von Programmen oder Skripten äußerst praktisch, ja sogar notwendig. Sie ermöglichen es uns, einen bestimmten Codeabschnitt eine bestimmte Anzahl von Malen auszuführen. Natürlich gibt es in der Bash mehrere Arten von Schleifen. Wir werden die Zyklen beschreiben für in, für, während, bis. Obwohl for in und for als unterschiedliche Syntaxen derselben Anweisung betrachtet werden, unterscheiden sie sich meiner Meinung nach stärker voneinander als while from Until.

Schleife mit Zähler für In:

Zyklus für in Dies ist eine Schleife mit einem Zähler. Der im Schleifenkörper befindliche Codeblock wird so oft wiederholt, wie Werte in der Liste des for in-Operators enthalten sind, und bei jeder Wiederholung wird die Zählervariable (hier heißt sie var, aber natürlich Sie können es beliebig nennen) hat den Wert des nächsten Elements der Liste.
Wenn sich das Schlüsselwort do in derselben Zeile wie das Wort for befindet, müssen Sie nach der Liste der Argumente (vor do) ein Semikolon einfügen.
Jedes der Elemente<список>kann mehrere Argumente enthalten. Dies ist nützlich, wenn Parametergruppen verarbeitet werden. In diesem Fall soll das Parsen aller Argumente erzwungen werden<списке>, müssen Sie die Set-Anweisung verwenden
Sie können eine Variable als Liste in einer for-Schleife verwenden.
IN<списке>Die for-Schleife kann Dateinamen verwenden, die wiederum Platzhalterzeichen enthalten können. Dies kann sehr nützlich sein, wenn Sie mit einer großen Anzahl von Dateien arbeiten.
Wenn<список>nicht in der for-Schleife angegeben ist, wird als solche die Variable $@ verwendet – eine Liste von Befehlszeilenargumenten.
Beim Erstellen einer Liste von Argumenten können Sie die Befehlsersetzung in einer for-Schleife verwenden.
Die Ausgabe der Schleife kann von stdout in eine Datei oder an einen anderen Ort umgeleitet werden (weitere Informationen hierzu finden Sie unter E/A-Umleitung).

Syntax:
für var in<список>
Tun
<выполняемые команды>
Erledigt

Beispiel:
für Namen in Name1 Name2 Name3 Name4
Tun
echo $names
Erledigt

Schleifenoperator für hat eine andere Schreibweise – sehr ähnlich der Syntax des for-Operators in der Sprache C. In diesem Fall werden beim Initialisieren der Zähler die Anfangswerte von Variablen oder einer Variablen gesetzt und nach jedem Schleifendurchlauf die Bedingung geprüft wird. Wenn die Prüfung „true“ zurückgibt, beginnt der nächste Durchlauf der Schleife. Im Block<приращение счётчиков>Der Wert unserer Variablenzähler muss sich unbedingt ändern (nicht unbedingt nach oben), damit wir bei der Überprüfung der Bedingung früher oder später den Wert false erhalten, sonst endet die Schleife nie. Eine sehr praktische und vor allem vertraute Option, wenn ein Vorgang eine bestimmte Anzahl von Malen wiederholt werden muss.

Mit einer ähnlichen Syntax:
für ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
Tun
<выполняемые команды>
Erledigt

Beispiel:
für ((var=1; var<= LIMIT ; var++))
Tun
echo $var
Erledigt

while-Schleife:

Dies ist eine ziemlich einfache Konstruktion, die den Zustand hinter dem Bediener überprüft während und wenn diese Bedingung wahr ist, führt es den Befehlsblock zwischen den Wörtern do und done aus und fährt dann erneut mit der Überprüfung der Bedingung fort. Wenn die Prüfung „Falsch“ zurückgibt, endet der Zyklus und die folgenden Befehle werden ausgeführt: Erledigt. Dafür muss unbedingt gesorgt werden<проверка условия>hing vom Code ab, der in der Schleife ausgeführt wird. Andernfalls erhalten Sie eine Endlosschleife, wenn sich das Ergebnis der Prüfung nicht ändert.
Das Standardeingabegerät für eine While-Schleife kann mit dem Umleitungsbefehl in eine Datei umgeleitet werden< в конце цикла.

Syntax:
während<Проверка условия>
Tun
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Erledigt

Beispiel:
while [ $var0 -eq 100 ]
Tun
echo $var
var++
Erledigt

Operator während kann mehrere Bedingungen haben. Aber nur der letzte von ihnen bestimmt die Möglichkeit, den Zyklus fortzusetzen. In diesem Fall unterscheidet sich die Syntax des Schleifenoperators von der üblichen.
Syntax(Ich wiederhole noch einmal, dass nur die letzte Bedingung die Ausführung der Schleife beeinflusst) :
während
<условие1>
<условие2>

<условиеN>
Tun
<выполняемые команды - тело цикла>
Erledigt

Bis-Schleife:

Operator bis ist while sehr ähnlich. Es wertet ebenfalls die Bedingung aus, führt jedoch den Schleifenkörper aus, wenn das Ergebnis der Berechnung falsch ist. Es mag ungewöhnlich erscheinen, aber Until wertet die Bedingung vor dem ersten Durchlauf der Schleife aus, z. B. while, und nicht danach. Wie bei for/in-Schleifen müssen Sie beim Platzieren des do-Schlüsselworts in derselben Zeile wie die Schleifendeklaration ein „;“-Zeichen einfügen. vorher tun.
Wie im vorherigen Fall ist es wichtig, sich daran zu erinnern, dass die Bedingung von den Operationen im Schleifenkörper abhängen muss, sonst wird unser Skript nie abgeschlossen.

Syntax:
bis<Проверка условия>
Tun
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Erledigt

Beispiel:
bis [ $var0 -gt 100] # Die Bedingung wird zu Beginn der Iteration überprüft.
Tun
echo $var
var--
Erledigt

Das reicht wahrscheinlich für den Moment. :) :)

  • zurück
  • Nach vorne

Neue Artikel:

  • Die Netzwerkerkennung lässt sich in Windows 7/8/2008/2012 nicht aktivieren
  • Fehler: Diese Anwendung konnte nicht gestartet werden, da sie das Qt-Plattform-Plugin „Windows“ nicht finden oder laden konnte.
  • Konfigurieren des automatischen Neustarts der rphost.exe-Arbeitsprozesse auf dem 1C 8.3-Server
  • So reduzieren Sie die Größe des Transaktionsprotokolls (.ldf) in MS SQL 2008/20012

    MS SQL führt wie jedes anständige industrielle DBMS zusammen mit der Datenbank Transaktionsprotokolle, die es Ihnen ermöglichen, den Status zurückzusetzen ...

0 Meeran Bala-Kumaran

Ich versuche wirklich zu verstehen, warum diese While-Schleife nie endet. Wenn die Schleife beginnt, ist meine LOC-Variable auf Testing/ gesetzt. Das Verzeichnis, das ich zum Testen dieses Programms erstellt habe, hat das folgende Layout:

Ich möchte, dass die Schleife endet, sobald auf alle Verzeichnisse die Funktion „Zählen“ angewendet wurde.
Hier ist, was ich versucht habe;

Ich habe die Zählfunktion überprüft und sie erzeugt keine Endlosschleife

Ich habe versucht, den Algorithmus manuell auszuführen

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") while [ $PARSE = "1" ] do if [[ $(AVAILABLEDIR[@]) == "" ]]; then PARSE=0 fi DIRBASE=$LOC für a in $(AVAILABLEDIR[@]); do LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" count done for a in $(LOCLIST[@]); do TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a if [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; dann weiter fi für a in $(TMPAVAILABLEDIR[@]); do TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" done NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" done AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" done

Ich habe wirklich Probleme und wäre für jede Eingabe sehr dankbar. Ich habe in den letzten zwei Stunden versucht, das herauszufinden.

Bash-Endlosschleife

4 Antworten

Sie sollten versuchen, das Skript mit dem Argument -x auszuführen oder es in die erste Zeile zu schreiben:

#!/bin/bash -x

Dann erzählt er dir alles, was er tut.

In diesem Fall bemerken Sie möglicherweise zwei Fehler:

    Sie laden TMPAVAILABLEDIR2 niemals neu

    Sie führen ls auch für reguläre Dateien aus.

Wenn Sie eine Rekursion wirklich vermeiden müssen, versuchen Sie Folgendes, ganz ohne Rekursion:

#!/bin/bash count() ( echo counting „$1“ ) todo=(Testing) while test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () für Verzeichnis in „$(doit[@])“ für Eintrag in „$dir“/* # Wenn das Verzeichnis leer ist, wird ein Eintrag mit dem Namen „*“ angezeigt. do test -e „$entry“ || continue # den Eintrag „*“ eines leeren Verzeichnisses überspringen count „$entry“ test -d „$entry“ || weiter todo+=("$entry") erledigt erledigt erledigt

Sagen Sie mir jedoch bitte, warum Sie keine Rekursion verwenden können. Ist das eine Art Allergie? Gelübde? Gibt es an Ihrem Wohnort lokale Gesetze gegen rekursive Software?

Sie haben geschrieben, dass Sie alle Schnitte „zählen“ möchten. Schauen Sie sich die Suchoptionen an:

Finden Sie $LOC -type d | while read dir; do cd $LOC cd $(dir) count done

oder kürzer (wenn Ihr Funktionszähler das Verzeichnis als Parameter 1 verwendet)

Finden Sie $LOC -type d | xargs zählen

Jetzt sehe ich, dass Sie weder find noch ls -R (rekursive Funktion) verwenden möchten. Dann sollten Sie Ihre eigene rekursive Funktion erstellen

Funktion parseDir ( ls -d */ $1 | while read dir; do count parseDir $1/$dir done )

Ich habe keine Ahnung, ob das funktionieren wird, aber es ist eine interessante Frage, über die ich ständig nachdenken musste. Viel Glück

Während wahr; tun für Wort in "$(echo *)" ; tun, wenn [[ -d "$word" ]] ; then d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;then f[$((j++))]="$PWD"/"$ Wort" fi done [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || Pause geschafft



Freunden erzählen