Was ist der portable und kanonische Weg, um zu testen, ob die Variable in einem Shell-Skript leer oder nicht definiert ist? Es sollte in allen sh-artigen Schalen funktionieren. Was ich jetzt mache ist etwas wie:
%Vor%und umgekehrt, etwas tun, wenn die Variable nicht leer / undefiniert ist:
%Vor%Und während diese für die Skripte funktionieren, die ich jetzt schreibe, möchte ich einen Weg kennen, der in jeder vernünftig kompatiblen sh ähnlichen Shell funktioniert in einer etwas obskuren Umgebung als ein Linux-PC mit GNU-Benutzerland und bash oder Strich .
Ich suche nach einer "Expertenantwort" von jemandem, der in verschiedenen Shell-Umgebungen erfahren ist und die Fallstricke von verschiedenen Wegen kennt, nicht eine Meinung wie "das sollte funktionieren".
Die Klammerkonstruktion [...]
ist Teil des POSIX-Standards und ungefährdet überall. Um zu testen, ob eine Variable leer ist, ist der in der Frage verwendete Fall if
perfekt:
Solange Sie sich erinnern als:
Eine nicht zitierte Variable unterliegt der Worttrennung. Wenn Sie also [ -z $STRING ]
(ohne Anführungszeichen um $STRING
) verwenden und $STRING
Leerzeichen enthält oder leer ist, sieht die Shell [ -z SEVERAL WORDS ]
oder [ -z ]
das sind beide Syntaxfehler - also nicht was du willst.
Ein alternativer Weg, um zu testen, ob eine Zeichenfolge in einer POSIX-Shell leer ist, ist die Verwendung von =
.
Beachten Sie jedoch, dass Sie niemals doppelte Gleichheitszeichen ( ==
) innerhalb von [...]
verwenden sollten! (Dies funktioniert nur in bash
, oder wenn sh
ein Link zu bash
ist - aber wenn es auf einem anderen Computer ausgeführt wird, auf dem sh
auf etwas anderes verweist, funktioniert nicht . ) Wenn Sie das doppelte Gleichheitszeichen verwenden möchten, sollten Sie auch doppelte Klammern [[...]]
haben (was nur in zsh
, bash
usw. funktioniert, aber nicht in einfachen POSIX-Shells wie dash
).
&&
oder ||
innerhalb [...]
Es könnte in einigen Shells funktionieren, aber es wird sicher nicht in allen funktionieren. Stattdessen schreiben Sie für ' und [...] && [...]
oder [... -a ...]
. Und für ' oder schreib [...] || [...]
oder [... -o ...]
.
Manchmal sehen Sie in wirklich alten Shell-Skripten Dinge wie die folgenden, um nach einer leeren Variablen zu suchen. Dies ist immer noch absolut gültig (aber sieht in meinen Augen etwas klobig aus) und ich habe noch nie eine Shell gefunden, die dies erfordert (obwohl meine Erfahrung zugegebenermaßen außerhalb von Linux begrenzt ist - vielleicht gibt es BSD-Shells, die das noch brauchen?) / p> %Vor%
Das Voranstellen eines Zeitraums soll verhindern, dass die Klammerkonstruktion [...]
verwechselt wird, wenn $STRING
zufällig -e
, -o
und andere Optionen enthält, die [...]
verwendet. Durch das Voranstellen einer Periode wird diese in eine Nicht-Option umgewandelt.
Ich habe noch nie gesehen, dass eine Shell diese Problemumgehung benötigt. (Dash braucht sie bestimmt nicht.) Also ist es wahrscheinlich sicher, das zu ignorieren.
Es ist wichtig, daran zu denken, dass eine leere Shell-Variable nicht dasselbe ist wie eine nicht gesetzte Shell-Variable - obwohl diese Unterscheidung nicht mit beiden Formen von [ test ]
gemacht werden kann. Alles, was test
tun kann, ist, über den Wert der Expansion einer Variablen zu berichten - es ist die Parametererweiterung, die das bestimmt. Zum Beispiel:
Nochmal:
%Vor% Mit [ test ]
:
Hoffentlich fährt es nach Hause:
%Vor%Wenn Sie portabel feststellen wollen, ob eine Variable leer ist, wird dies tun:
%Vor%Ich denke, Sie könnten die Erweiterung der Shell-Parameter für Fälle wie diese sehr gut nutzen und in einigen Fällen sogar zwei Fliegen mit einer Klappe schlagen (siehe erstes Beispiel). Dies sollte auf jeden Fall tragbar sein. Es folgt ein unvollständiges Kopieren / Einfügen aus den POSIX-Shell-Richtlinien der offenen Gruppe, die Sie hier finden: Ссылка
${parameter:-word}
unset
oder null
ist, wird die Wortausdehnung ersetzt. Andernfalls wird der Wert des Parameters ersetzt. ${parameter:=word}
unset
oder null
ist, soll die Erweiterung des Wortes dem Parameter zugewiesen werden. In allen Fällen muss der endgültige Wert des Parameters ersetzt werden. Nur Variablen, keine Positionsparameter oder spezielle Parameter können auf diese Weise zugewiesen werden. ${parameter:?[word]}
unset
oder null
ist, wird die Erweiterung des Wortes (oder eine Nachricht, die angibt, dass es nicht gesetzt ist, wenn das Wort weggelassen wird) in den Standardfehler geschrieben und die Shell wird mit einem Nicht-Null-Exit-Status beendet. Andernfalls wird der Wert des Parameters ersetzt. Eine interaktive Shell muss nicht beendet werden. ${parameter:+word}
unset
oder null
ist, wird null
ersetzt. andernfalls soll die Wortverbreiterung ersetzt werden. BEISPIELE:
${parameter:-word}
ls
nur ausgeführt, wenn x
ist null
oder unset
. (Die% subsync-Befehlsersatznotation wird unter Befehlsersetzung erläutert.)
%Code%
$( ls)
BEARBEITEN:
Ich habe gerade Ashishs One-Liner bemerkt, und weil es sich irgendwie billig angefühlt hat, würde ich gerne etwas tun . Also hier ist ein POSIX-Parameter-Erweiterung Set-Test One-Liner:
%Vor%Nun, immer noch billig, schätze ich.
EDIT2:
Also habe ich das gerade bemerkt: "... während diese für die Skripte funktionieren, die ich jetzt schreibe, würde ich gerne einen Weg finden, der in jeder vernünftig kompatiblen sh-ähnlichen Shell funktioniert, sogar in einigen mehr obskure Umgebung als ein Linux-PC mit GNU-Benutzerland und Bash oder Dash ... "
Es tut mir leid, dass ich kein Experte bin, aber ich habe zuerst die folgende Methode zur Definition wichtiger Shell-Variablen aus Argumenten ausgewählt, die nach dem Durchforsten einiger ziemlich professionell geschriebener initramfs-busybox-Skripte übergeben wurden oder nicht. Es wird überall so wie erwartet funktionieren.
Es ist ziemlich schön, weil Sie die Variablen nur auf die Standardbedingung setzen, wenn der Benutzer sie nicht ohne zusätzliche Arbeit definiert, um zu überprüfen, ob sie wirklich funktionieren. Es gibt natürlich Tonnen von anderen Anwendungen, ich bin einfach nicht schlau genug, sie so zu benutzen, wie ich sollte.
%Vor%EDIT3:
phs hat zu Recht gesagt, dass seine Methode auf leere Variablen prüft, die nicht fehlen, wie in der Frage gestellt wurde. Diese Methode kann dasselbe tun, je nachdem, ob der mittlere Doppelpunkt verwendet wird. Ich habe aus den POSIX-Richtlinien unten eine Art Mist-Tabelle kopiert, um dies zu demonstrieren.
%Vor%Sie müssen nicht hineingehen, wenn Sie eine andere Leiter haben, außer Sie haben große Codes, die in Testvariablen laufen
ein linner Beispiel
%Vor%Klicken Sie hier für weitere Beispiele.