IT

While- und Until-Schleifen in PowerShell und Batch

Eine der absolut grundlegendsten Funktionen einer Programmiersprache sind neben If- und Else-Abfragen wohl Schleifen. Nur mit diesen ist es möglich eine Aktion so oft zu wiederholen bis eine bestimmte Bedingung zutrifft oder nicht mehr gegeben ist. In der PowerShell kann man die gängigen For-Loops, ForEach-Loops, (Do-)While und (Do-)Until-Schleifen verwenden. In Batch-Dateien gibt es eigentlich nur For-Schleifen und den Rest muss man sich selber bauen. In diesem Artikel zeige ich für PowerShell und Batch wie es funktioniert.

Grundsätzliches zu Schleifen bzw. Loops

Die Nutzung von Schleifen (Englisch: Loops) dürfte in jeder Programmiersprache ein elementares Steuerelement sein, das benötigt wird um Abläufe zu wiederholen bis ein gewünschtes Ergebnis erreicht wird. Außer bei einer meist eher unbeabsichtigt erstellten Endlosschleife sind Schleifen an eine zu erfüllende Bedingung geknüpft. Ist diese erreicht wird die Schleife wieder verlassen und der nachfolgende Programm- oder Skriptcode wird ausgeführt.

Kurzüberblick der Schleifen in PowerShell

Wer nur kurz eine Auffrischung braucht wie genau die Schleifen in PowerShell zu nutzen sind findet hier eine Übersicht:

While-Schleife in PowerShell

Do-While-Schleife in PowerShell

Do-Until-Schleife in PowerShell

ForEach-Schleife in PowerShell

For-Schleife in PowerShell

 

Schleifen in Batch-Dateien bzw. der Kommandozeile

In Batch-Dateien ist vieles nicht vorgesehen gewesen und mit Bordmitteln auch nicht möglich. So gibt es keine standardmäßigen Möglichkeiten Schleifen mit beliebigen Abbruchbedingungen einzusetzen. Außer einer For-Schleife steht nichts zur Auswahl. Ich benötigte eine Schleife mit einer bestimmten maximalen Anzahl an Durchläufen. Diese sollte aber beim erwarteten Ergebnis auch schon früher abbrechen. Das lässt sich mit einer For-Schleife nicht realisieren. Denn man kann aus dieser nicht per goto-Befehl „ausbrechen“. Somit würde die Maximalanzahl an Durchläufen immer durchgeführt werden. Auch wenn das eigentliche Ziel schon beim ersten Versuch erreicht wurde. Mit PowerShell wäre das einfach gewesen. Das ist aber trotzdem kein Problem.

Glücklicherweise kann man sich auch in einer so rudimentären „Sprache“ wie bei Batch-Dateien die anderen Schleifenarten wie While– und Until-Schleifen einfach selber bauen. Zumindest solange man If-Abfragen und Sprungmarken mittels goto nutzen kann. Dies ist aus Performancegründen aber eigentlich zu unterlassen. Denn dieses Herumgespringe im Code erhöht wohl die CPU-Last. Lediglich der Komfort leidet natürlich und der Code ist unübersichtlicher als es in einer vernünftigen Programmiersprache der Fall wäre. Aber who cares?

In folgendem Beispiel ist eine Zählschleife mit einfachen Mitteln umgesetzt worden:

Diese Schleife produziert die gleiche Ausgabe wie folgende For-Schleife:

Nämlich die einfache Ausgabe des je Durchlauf aktuellen Wertes der Zählvariable:

In PowerShell sähe das sehr einfach so aus:

… oder so als For-Schleife:

 

Schleifen in der PowerShell

Da es sich bei der PowerShell um eine moderne Skriptsprache handelt, hat man es hier einfacher als in der alten Kommandozeile. Die meisten Schleifentypen stehen einem grundsätzlich von Hause aus zur Verfügung und müssen nicht durch eigene Konstruktionen nachgebaut werden. Das wäre auch gar nicht so einfach möglich, da in der PowerShell bewusst auf Sprungmarken bzw. den goto-Befehl, wie man ihn aus Batch-Dateien kennt, verzichtet worden ist. Hierdurch soll „Spaghetti“-Code eingedämmt werden. Dieser entsteht unweigerlich wenn man im Code wild hin- und herspringt.

 

Flow-Chart einer While-SchleifeWhile-Schleifen

Eine While-Schleife wiederholt die Anweisungen solange die Prüfung der Bedingung „True“ als Wert zurückgibt. Ist also direkt am Anfang die Bedingung „False“, wird die Schleife nicht ein einziges Mal durchlaufen. Es handelt sich hierbei um eine sogenannte „kopfgesteuerte“ Schleife, weil die Prüfung der Bedingung direkt am Anfang der Schleife stattfindet. Dies kann man auch schön in dem Ablaufplan sehen.

Mit einer if-Abfrage, einer Hilfsvariable und goto ließe sich das in jeder beliebigen Programmiersprache z. B. so realisieren:

…oder ohne die Hilfsvariable, wenn eine Prüfung auf eine Bedingung nicht zu umfangreich ist und sich der Code so etwas vereinfachen lässt:

In der PowerShell gibt es stattdessen die Möglichkeit ohne Hilfsmittel eine While-Schleife zu verwenden:

Auf jeden Fall muss sichergestellt werden, dass die Bedingung irgendwann „False“ wird. Ansonsten hat man eine Endlosschleife erstellt.

 

Flow-Chart einer Do-While-SchleifeDo-While-Schleifen

Im Gegensatz zur While-Schleife wird eine Do-While-Schleife mindestens einmal durchlaufen. Solange bis die Bedingung „False“ ist. Hierfür muss man nur das vorherige Beispiel umstellen. Der Anweisungsblock befindet sich nun vor der Bedingungsprüfung, also vor dem if-Block. Die Prüfung der Bedingung findet nun am „Fuß“ der Schleife statt. Es handelt sich also um eine „fußgesteuerte“ Schleife.

Auch diese lässt sich auf die gleiche Weise wie die While-Schleife in Batch realisieren:

 

Das ganze geht natürlich auch bei der Do-While-Schleife ohne Hilfsvariable und wirkt dann aufgeräumter:

In der PowerShell kann man vergleichsweise einfach eine Do-While-Schleife nutzen, bspw. so:

Auch bei der Do-Variante Fall muss sichergestellt werden, dass die Bedingung irgendwann „False“ wird, um keine Endlosschleife zu bauen.

 

Flow-Chart einer Until-SchleifeUntil-Schleifen

Um eine Until-Schleife zu realisieren, müsste man theoretisch nur die Bedingungsprüfung in der While-Schleife umstellen. Die Schleife muss in diesem Fall solange laufen wie die Bedingung „False“  oder eher bis sie „True“ zurück liefert. Denn eine Until-Schleife stoppt sobald die Bedingung „True“ wird. Es handelt sich um eine „kopfgesteuerte“ Schleife.

Bei der umgekehrten While-Schleife wird aber kein richtiger Abbruch der Schleife genutzt. Vielmehr wird immer noch eine While-Schleife genutzt, die einfach nur andersherum prüft. Deshalb habe ich mich für folgende explizitere Abbruch-Variante entschieden:

 

In der PowerShell gibt es tatsächlich keine normale Until-Schleife! Eine solche Anweisung wird mit einer Fehlermeldung quittiert:

Das kann unter Umständen doof sein, da der Anweisungsblock der Do-Until-Schleife auf jeden Fall einmal ausgeführt wird. Selbst wenn die Abbruchbedingung schon beim erstmaligen Durchlauf der Schleife erfüllt ist. Denn die Überprüfung findet erst im Schleifenfuß, also am Ende, statt. Wenn die Schleife in dem Fall gar nicht durchlaufen werden soll, kann man sich nur auf unschöne Arten behelfen:

Entweder man setzt eine if-Abfrage um die Schleife herum um eine  Ausführung auszuschließen, falls die Abbruchbedingung bereits gegeben ist:

Oder man nutzt einen ebenfalls unschönen break-Befehl in der Schleife um aus dieser auszubrechen:

Schöner finde ich es in einem solchen Fall stattdessen auf eine While-Schleife zurückzugreifen und die Bedingung einfach so umzubauen, dass es auch mit diesem Schleifentypen realisiert werden kann. Für das vorherige Do-Until-Beispiel eventuell so:

In diesem Beispiel ist noch zu bedenken, dass man sich eventuell eine Endlosschleife baut, falls der Wert der Variable $test bereits beim ersten Schleifendurchlauf bei 11 liegt. Dann würde die Schleife endlos laufen und immer weiter hochzählen. Für eine Zählschleife ist das Konstrukt also eher nicht geeignet, sondern wenn man z. B. einen String untersucht.

 

Do-Until-Schleifen

Flow-Chart einer Do-Until-SchleifeFür eine Do-Until-Schleife muss man nur, wie schon bei der Do-While-Schleife, den Anweisungsblock vor die Bedingungsprüfung setzen und erhält dann eine „fußgesteuerte“ Schleife. Dieser wird dann mindestens einmal durchlaufen:

In der PowerShell kann man vergleichsweise einfach eine Do-Until-Schleife nutzen, bspw. so:

Auch aus der Do-Variante kann man versehentlich eine Endlosschleife machen, falls die Abbruchbedingung niemals eintritt.

 

Welche Schleife wann nutzen?

Ich stelle mir selber die Frage, wann man welchen Schleifentyp nutzen sollte und vermutlich gibt es darauf verschiedene Antworten und Präferenzen. Dies ist vermutlich immer sehr individuell entsprechend der zu erledigenden Aufgabe zu entscheiden. Grundsätzlich kann man viele Dinge, die man mit einer While-Schleife machen würde z. B. auch mit einer Until-Schleife erledigen und umgekehrt.

Die Entscheidung sollte wohl danach getroffen werden ob man eher eine Abbruchbedingung (Until) oder eine Ausführungsbedingung (While) benötigt. Wichtiger ist vermutlich die Frage ob man die fuß- oder die kopfgesteuerte Variante nutzen sollte und ob dadurch eine zumindest einmalige Ausführung des Anweisungsblocks gewünscht ist.

 

Fazit

Auch wenn sich die Schleifen in der Kommandozeile basteln lassen, stellt die PowerShell ein komfortableres und moderneres Skriptumfeld dar. Wenn möglich sollte man die PowerShell bevorzugen um „saubere“ Skripte zu schreiben und „schöne“ Varianten der verschiedenen Schleifentypen verwenden zu können.

Lässt sich dies z. B. aufgrund eines veralteten Zielsystems nicht realisieren, sollte man versuchen die selbstgebastelten While– oder Until-Schleifen aufgrund der höheren CPU-Last zu vermeiden. Vermutlich ist das in den meisten Fällen aufgrund der vorhandenen Leistung des Systems aber nicht so ein große Problem.

 

 
 
Tobias Langner

Ich arbeite seit mehreren Jahren als Software-Release-Manager, zuvor als IT-Administrator, bin ausgebildeter Fachinformatiker für Systemintegration und Studium-"Pausierer" an der FernUni Hagen. Achtung: Für die Richtigkeit der zur Verfügung gestellten Informationen, Skripte, etc. übernehme ich keine Gewähr. Deren Nutzung geschieht ausdrücklich auf eigene Gefahr!

Tobias Langner

Ich arbeite seit mehreren Jahren als Software-Release-Manager, zuvor als IT-Administrator, bin ausgebildeter Fachinformatiker für Systemintegration und Studium-"Pausierer" an der FernUni Hagen. Achtung: Für die Richtigkeit der zur Verfügung gestellten Informationen, Skripte, etc. übernehme ich keine Gewähr. Deren Nutzung geschieht ausdrücklich auf eigene Gefahr!

Alle Beiträge ansehen von Tobias Langner →

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert