Portable Möglichkeit, die Leerheit einer Shell-Variablen zu überprüfen

8

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".

    
hyde 05.11.2013, 07:41
quelle

5 Antworten

3

Haftungsausschluss : Ich betrachte mich selbst nicht als Experte für Shells.

AFAIK, der Befehl test und die Flags -z und -n sind Teil des POSIX-Standards. Daher sollten Sie sie verwenden, wenn Sie sie auf vielen Plattformen verwenden.

    
rvidal 05.11.2013, 14:34
quelle
4

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:

%Vor%

Solange Sie sich erinnern als:

Immer zitieren Sie die Variablen

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.

Verwenden Sie immer nur ein Gleichheitszeichen

Ein alternativer Weg, um zu testen, ob eine Zeichenfolge in einer POSIX-Shell leer ist, ist die Verwendung von = .

%Vor%

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 ).

Verwenden Sie nicht && 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 ...] .

Ancient stuff

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.

    
zrajm 23.07.2014 00:41
quelle
2

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:

%Vor%

Nochmal:

%Vor%

Mit [ test ] :

%Vor%

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}

  • Verwenden Sie Standardwerte. Wenn der Parameter unset oder null ist, wird die Wortausdehnung ersetzt. Andernfalls wird der Wert des Parameters ersetzt.

${parameter:=word}

  • Standardwerte zuweisen Wenn der Parameter 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]}

  • Geben Sie einen Fehler an, wenn Null oder Unset. Wenn der Parameter 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}

  • Verwenden Sie den alternativen Wert. Wenn der Parameter unset oder null ist, wird null ersetzt. andernfalls soll die Wortverbreiterung ersetzt werden.

BEISPIELE:

${parameter:-word}

  • In diesem Beispiel wird ls nur ausgeführt, wenn x ist null oder unset . (Die% subsync-Befehlsersatznotation wird unter Befehlsersetzung erläutert.) %Code%

$( ls)

%Vor%

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%     
mikeserv 20.11.2013 00:27
quelle
0

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.

    
Ashish 05.11.2013 09:53
quelle
0

Portable und Canonical sind zwei verschiedene Dinge.

Für portable, den Test sehe ich in mehreren autoconf Skripts ist:

%Vor%

Dies testet auf Leerheit, nicht auf Abwesenheit.

    
phs 20.11.2013 00:36
quelle

Tags und Links