Website-Suche

So verwenden Sie Bash-Subshells in if-Anweisungen


Wenn Sie jemals Bash-Subshells ($ (...)) verwendet haben, wissen Sie, wie flexibel Subshells sein können. Es sind nur wenige Zeichen erforderlich, um eine Subshell zu starten, um alles Erforderliche inline einer anderen Anweisung zu verarbeiten. Die Anzahl der möglichen Anwendungsfälle ist nahezu unbegrenzt.

Wir können auch Bash-Subshells innerhalb von if-Anweisungen verwenden, die mit der Anweisung übereinstimmen. Auf diese Weise erhalten Benutzer und Entwickler viel zusätzliche Flexibilität, wenn es darum geht, Bash-if-Anweisungen zu schreiben.

Wenn Sie noch nicht mit Bash-If-Anweisungen vertraut sind (oder mehr darüber erfahren möchten), lesen Sie bitte unseren Artikel Bash-If-Anweisungen: Wenn Elif sonst dann Fi.

In diesem Tutorial lernen Sie:

  • Wie man Bash-Subshells in if-Anweisungen einbindet
  • Fortgeschrittene Methoden zum Einbinden von Bash-Subshells inline mit anderen Befehlen
  • Beispiele, die die Verwendung von Bash-Subshells in if-Anweisungen veranschaulichen

So verwenden Sie Bash-Subshells in if-Anweisungen

Verwendete Softwareanforderungen und Konventionen

Beispiel 1: Einfach anfangen

Schauen wir uns zunächst ein einfaches Beispiel an. Beachten Sie, dass diese Anweisungen, obwohl sie hier auf der Kommandozeile ausgeführt werden, auch in ein Bash-Shell-Skript eingebunden werden können (eine reine Textdatei, vorzugsweise mit der Erweiterung .sh, und mit dem Befehl chmod +x myscript.sh als ausführbar markiert werden kann – wobei myscript.sh ein Beispieldateiname ist). Wir führen auch einen Fehler ein, um die Dinge interessanter zu machen.

if [ "test" == "$(echo 'test')" ]; then echo 'Matches!'; else echo 'Does not match!'; fi
Matches!
if [ "test" == "$(echo 'incorrect')" ]; then echo 'Matches!'; else 'Does not match!'; fi
Does not match!: command not found

Im ersten Befehl verwenden wir einen einfachen Test (if [ "some_text" == "some_other_text" ]; dann ...), um die Gleichheit zwischen zwei Zeichenketten zu überprüfen. Für den zweiten String haben wir eine Bash-Subshell ($ (..)) gestartet, um das Wort test auszugeben. Das Ergebnis ist, dass test matches test und somit die Befehle nach der then-Klausel ausgeführt werden, in diesem Fall wird echo 'Matches!' ausgeführt und Matches! ausgegeben.

Im zweiten Befehl ändern wir den Befehl echo in eine falsche Textübereinstimmung, indem wir die Subshell echo/ausgabe incorrect ($ (echo 'incorrect')) lassen. Wir erhalten einen seltsam aussehenden Fehler zurück. Schauen Sie genau hin, können Sie den Fehler erkennen? Vergleichen Sie auch den zweiten Befehl mit dem ersten.

Das Problem ist, dass in unserem zweiten Befehl die else-Klausel (die ausgeführt wird, wenn die Gleichheitsübereinstimmung fehlschlägt, d.h. 'was sonst zu tun ist, wenn die if-Anweisung nicht wahr war) einen echo-Befehl verpasst. Während es flüssig lesen kann (wenn ... dann Echo ... sonst ...) Der Befehl ist falsch, da er ein zusätzliches Echo erfordert. Das Ergebnis ist, dass die Bash-Shell versucht, Does not match! als Literalbefehl auszuführen.

Lassen Sie uns das in Ordnung bringen!

if [ "test" == "$(echo 'incorrect')" ]; then echo 'Matches!'; else echo 'Does not match!'; fi
Does not match!

Viel besser. Und wir können sehen, dass unsere Subshell, ihr Echo und die vollständige if-Anweisung korrekt ausgeführt werden. Großartig, lassen Sie uns ein wenig tiefer eintauchen.

Beispiel 2: Eine etwas komplexere if-basierte Subshell-Anweisung

VAR1='abc'; if [[ "$(echo "${VAR1}")" == *"b"* ]]; then echo 'Matches!'; else echo 'Does not match!'; fi
Matches!
VAR1='adc'; if [[ "$(echo "${VAR1}")" == *"b"* ]]; then echo 'Matches!'; else echo 'Does not match!'; fi
Does not match!

Hier setzen wir eine Variable VAR entweder auf abc oder adc und geben diese Variable als nächstes aus, wiederum mit einer Subshell, gegen das Vorhandensein von b in der Zeichenkette. Beachten Sie, dass das ursprüngliche Sternchen (*) des ursprünglichen Sternchens der "b"-Vergleichsklausel alles vor dieser Zeichenfolge anzeigt und das Suffix Sternchen (*) in ähnlicher Weise alles nach dieser Zeichenfolge bedeutet. Wir können sehen, wie b im ersten abc-String gefunden wurde, aber nicht im zweiten Befehl/String, in dem adc als Vergleichsstring verwendet wurde.

Beachten Sie auch, dass wir diesmal [[...]] Klammern für die if-Anweisung verwendet haben. Dies hat nichts mit der Verwendung von Subshells zu tun, und es ist einfach ein neuerer Bash-Standard für das Schreiben von Anweisungen, die für zusätzliche oder andere Anwendungsfälle als die traditionelle [...] Syntax verwendet werden können. Wir benötigen es hier, um das spezielle b-Matching durchzuführen, das wir versuchen, indem wir das Sternchen (*) Präfix und das Suffix für die "b"-Vergleichsklausel verwenden.

In einer if-Anweisung mit einfachen [...] Klammern würde dies fehlschlagen:

if [ "abc" == *"b"* ]; then echo 'Matches!'; else echo 'Does not match!'; fi
Does not match!
if [[ "abc" == *"b"* ]]; then echo 'Matches!'; else echo 'Does not match!'; fi
Matches!

Da die if [...] Syntax das Sternchen (*) Präfix und Suffix der "b" compare-Klausel nicht erkennt und man stattdessen [[...]] Klammern verwenden muss.

Eine weitere Sache, die zu beachten ist, ist, dass wir dieses Mal doppelte Anführungszeichen (") innerhalb der Subshell verwendet haben (anstelle der einfachen Anführungszeichen wie im ersten Beispiel): Wenn man eine Subshell startet, ist eine solche Verwendung von doppelten Anführungszeichen nicht nur erlaubt, sondern ich kann sie für verschiedene Anwendungsfälle sehr empfehlen. Dies ist praktisch in einigen Situationen, in denen viel komplexes Parsen stattfindet und eine Mischung aus einfachen und doppelten Anführungszeichen erforderlich ist. Die doppelten Anführungszeichen beenden nicht die Anführungszeichen, die vor und außerhalb der Subshell gestartet wurden.

Bitte beachten Sie, dass man bei den meisten der vorherigen Beispiele die Subshell einfach weglassen und einen einfachen Vergleich direkt mit z.B. der Variablen hätte durchführen können, d.h.:

VAR1='abc'; if [[ "${VAR1}" == *"b"* ]]; then echo 'Matches!'; else echo 'Does not match!'; fi
Matches!

Wir haben uns jedoch dafür entschieden, Subshells mit echo einzuführen (effektiv eine Null-Operation, d.h. effektiv das Gleiche wie die Verwendung der Variablen oder des betreffenden Textes), da dies hervorheben würde, dass 1) Subshells effektiv funktionieren und 2) dass sie aus if-Anweisungen heraus verwendet werden können.

Beispiel 3: Erweiterte if-basierte Subshell-Anweisungen

Wir müssen die Verwendung unserer Subshell-Anweisungen innerhalb von if-Anweisungen nicht auf einen einzelnen Befehl beschränken, noch auf die Verwendung von echo allein. Lassen Sie uns ein kleines Setup erstellen:

touch a
ls --color=never ./a | wc -l 
1

Wir haben eine Datei mit dem Namen a erstellt und die Anzahl der Zeilen gezählt (mit wc -l, einem Zählwerkzeug, das die Anzahl der Zeilen mit der Option -l zählen kann). Wir haben auch dafür gesorgt, dass die Option --color=never in ls eingeführt wurde, um Probleme beim Parsen zu vermeiden, wenn die Farbcodierung des Terminals verwendet wird.

Als Nächstes arbeiten wir diese Anweisungen direkt in if-Anweisungen ein:

if [ -z "$(ls --color=never ./a | wc -l)" ]; then echo "Empty directory output!"; fi
if [ "$(ls --color=never ./a | wc -l)" -eq 1 ]; then echo "Exactly one file found!"; fi
Exactly one file found!

Hier verwenden wir die gleichen ls ... wc -l zweimal direkt aus einer if-Anweisung heraus codieren. Die erste if-Anweisung, die -z verwendet, prüft, ob der Text zwischen Anführungszeichen (die erste Option für die -z if-Anweisung) leer ist. Es ist nicht so, dass der Befehl ls in diesem Fall eine Ausgabe liefert, da wir die Datei a erstellt haben.

Im zweiten Befehl testen wir tatsächlich, ob die Ausgabe unseres ls ... wc -l ist gleich 1, indem die Option -eq test in der if-Anweisung verwendet wird. EQ steht für Gleich. Beachten Sie, dass -eq (und es ist umgekehrt, dass -ne ungleich ist) nur für Zahlen verwendet werden kann. Verwenden Sie für textbasierte Zeichenfolgen stattdessen == (gleich) und != (ungleich).

Die Ausgabe des Befehls (Genau eine Datei gefunden!) ist korrekt, und unsere if-Anweisung mit integrierter Multi-Command-Subshell funktioniert einwandfrei!

Interessant ist auch, dass der erste Vergleichswert in der zweiten if-Anweisung (d.h. $ (ls --color=never ./a | wc -l) mit Ausgabe 1) numerisch ist. Warum haben wir also zwei doppelte Anführungszeichen ("... ") um die Subshell-Anweisung herum? Das hat nichts mit Subshells zu tun, sondern damit, wie if in Bash funktioniert, und man kennt diesen Trick oder diese Abkürzung vielleicht noch nicht; Bitte beachten Sie Folgendes:

V='1 1'
if [ ${V} -eq 0 ]; then echo '0'; fi
bash: [: too many arguments
if [ "${V}" -eq 0 ]; then echo '0'; fi
bash: [: 1 1: integer expression expected
V=0
if [ "${V}" -eq 0 ]; then echo '0'; fi
0

Mit anderen Worten, die Verwendung von doppelten Anführungszeichen ist eine etwas sicherere Methode zum Programmieren von Bash-if-Anweisungen, selbst wenn es sich bei der Bedingung um eine numerische Bedingung handelt. Es schützt davor, dass komplexere Zeichenfolgen als einzelne Elemente und nicht als einzelner Wert interpretiert werden, und es gibt eine korrekte Fehlermeldung (ganzzahliger Ausdruck erwartet) anstelle des mehrdeutigeren bash: [: too many arguments error.

Es spielt für Bash auch keine Rolle, dass Sie etwas vergleichen, das eine Textzeichenfolge zu sein scheint (wie durch "... ") mit einem numerischen Wert; Es funktioniert, vorausgesetzt, die Zahl ist numerisch. Und wenn dies nicht der Fall ist, wird immer noch eine bessere Fehlermeldung angezeigt, die darauf hinweist, dass die Zeichenfolge, wie zu sehen, nicht numerisch ist. Zusammenfassend lässt sich sagen, dass es besser ist, Ihre Subshell, Ihren Text oder Ihre Variable immer in doppelten Anführungszeichen zu setzen, auch wenn Sie numerische Elemente vergleichen. Um zu beweisen, dass dies gut funktioniert, sollten Sie Folgendes berücksichtigen:

if [ "1" -eq "1" ]; then echo 'y'; fi
y
if [ "1" -eq "0" ]; then echo 'y'; fi

Schlussfolgerung

In diesem Artikel haben wir uns mit dem Einbinden von Bash-Unterschalen in if-Anweisungen befasst. Wir haben mehrere Beispiele untersucht, von einfach bis fortgeschritten, wie wir Bash-Subshells in if-Anweisungen verwenden können. Wir haben uns auch ein wenig mit der Verwendung von doppelten Anführungszeichen beim Vergleich beschäftigt, selbst beim Vergleich numerischer Felder. Die Verwendung von Subshells in anderen Befehlen, und in diesem Fall if-Anweisungen, ist eine leistungsstarke Möglichkeit, Ihre Bash-Skripting-Fähigkeiten zu erweitern. Genießen!

Verwandte Artikel: