it-swarm.com.de

Test auf leere Zeichenkette mit X ""

Ich weiß, dass ich in Bash mit -z Auf eine leere Zeichenfolge testen kann:

if [[ -z $myvar ]]; then do_stuff; fi

aber ich sehe viel Code geschrieben wie:

if [[ X"" = X"$myvar" ]]; then do_stuff; fi

Ist diese Methode portabler? Ist es nur eine historische Kruft aus der Zeit vor -z? Gilt es für POSIX-Shells (obwohl ich es in Skripten gesehen habe, die auf bash abzielen)? Bereit für meine Geschichts-/Portabilitätsstunde.


Dieselbe Frage wurde bei Server-Fehler gestellt als Wie wird festgestellt, ob eine Bash-Variable leer ist? , aber niemand gab eine Erklärung an , warum Sie sehen Code mit dem Zeug X"".

74
mgalgs

Grundsätzlich war das Verhalten von test in längst vergangenen Zeiten komplexer und nicht systemübergreifend einheitlich definiert (daher musste portabler Code sorgfältig geschrieben werden, um nicht portierbare Konstrukte zu vermeiden).

Insbesondere bevor test eine eingebaute Shell war, war es eine separate ausführbare Datei (und beachten Sie, dass MacOS X immer noch /bin/test und /bin/[ als ausführbare Dateien). Wenn dies der Fall war, schreiben Sie:

if [ -z $variable ]

wann $variable war leer würde das Testprogramm über seinen Alias ​​aufrufen [ mit 3 Argumenten:

argv[0] = "["
argv[1] = "-z"
argv[2] = "]"

weil die Variable leer war, gab es nichts zu erweitern. Die sichere Art, den Code zu schreiben, war also:

if [ -z "$variable" ]

Dies funktioniert zuverlässig und übergibt 4 Argumente an die ausführbare Datei test. Zugegeben, das Testprogramm ist seit Jahrzehnten in den meisten Shells integriert, aber alte Geräte sterben schwer, und bewährte Methoden, die bereits vor längerer Zeit erlernt wurden, auch.

Das andere Problem, das durch das X-Präfix behoben wurde, war, was passiert ist, wenn Variablen führende Bindestriche enthalten oder Gleichheitszeichen oder andere Komparatoren enthalten. Betrachten Sie (ein nicht ganz gutes Beispiel):

x="-z"
if [ $x -eq 0 ]

Ist das ein leerer Stringtest mit einem streunenden (fehlerhaften) Argument oder ein numerischer Gleichheitstest mit einem nicht numerischen ersten Argument? Verschiedene Systeme gaben unterschiedliche Antworten, bevor POSIX das Verhalten um 1990 standardisierte. Der sichere Weg, damit umzugehen, war also:

if [ "X$x" = "X0" ]

oder (nach meiner Erfahrung seltener, aber völlig gleichwertig):

if [ X"$x" = X"0" ]

Es waren alles Edge-Fälle wie dieser, verbunden mit der Möglichkeit, dass der Test eine separate ausführbare Datei war, was bedeutet, dass portabler Shell-Code immer noch häufiger doppelte Anführungszeichen verwendet, als die modernen Shells tatsächlich benötigen, und die X-Präfix-Notation wurde verwendet Stellen Sie sicher, dass die Dinge nicht falsch interpretiert werden.

116

Ah, das ist eine meiner bevorzugten Fragen und Antworten, weil ich mir die Antwort ausgedacht habe, als ich nur darüber nachgedacht habe. Das X wird nur für den Fall gesetzt, dass der String mit einem - Beginnt, das als Flag für den Test verwendet werden kann. Wenn Sie ein X voranstellen, wird dieser Fall nur entfernt, und der Vergleich kann weiterhin durchgeführt werden.

Ich mag das auch, weil diese Art von Trick fast ein Erbe der Vergangenheit ist, der ältesten Zeiten des Rechnens, und Sie stoßen darauf, wenn Sie versuchen, einige der portabelsten Shell-Skripte zu lesen (autoconf, configure, etc.)

11
Diego Sevilla