Bash-Skript [x $ 1 = x]

21

Ich lese ein Bash-Skript. Ich verstehe nicht, was da vor sich geht.

#!/bin/sh
[ x$1 = x ] 

Was ist in der zweiten Zeile los und was [ x$1 = x ] bedeutet das?

Bob
quelle

Antworten:

27

Das prüft, dass $1leer ist, obwohl es in Anführungszeichen gesetzt werden sollte (identisch mit [ -z "$1" ]). Einige sehr alte Shells haben leere Zeichenfolgen nicht richtig verarbeitet, daher haben Autoren portabler Skripte diesen Überprüfungsstil übernommen. Es war jahrzehntelang nicht notwendig, aber die Leute machen es immer noch so, weil die Leute es immer noch so machen.

Kevin
quelle
Ja, du solltest es nicht mehr so ​​machen und einen moderneren Stil annehmen. Es sei denn, Sie arbeiten an einem PDP11.
MacLemon
4
Es geht nicht so sehr um leere Saiten. [ x$1 = x ]ist immer noch falsch, [ "x$1" = x ]wäre aber für shells die ein problem haben wo $1ist !oder (oder -n.... [ "" = "$1" ]und case $1 in "")wäre auch ok.
Stéphane Chazelas
2
@MacLemon, so weit muss man nicht zurück gehen. [ -z "$1" ]und [ "$1" = "" ]funktionieren immer noch nicht mit / bin / sh von Solaris 10, dem ersteren mit dash-0.5.4.
Stéphane Chazelas
1
extra +1 für den letzten Satz!
Glenn Jackman
1
@glennjackman, dieser letzte Satz ist falsch. Solaris 10 ist immer noch die am weitesten verbreitete Version von Solaris und [ "$1" = "" ]funktioniert immer noch nicht mit Solaris /bin/sh(obwohl Sie es dort verwenden möchten /usr/xpg4/bin/sh, nicht /bin/sh). Diesbezüglich wurde Dash im Januar 2009 festgelegt.
Stéphane Chazelas,
8

Eckige Klammern kennzeichnen einen Test , daher ist [ x$1 = x]without ifoder ähnliches bedeutungslos, obwohl syntaktisch in Ordnung.

Es soll als wahr gewertet werden, wenn es x$1erweitert wird x, und als falsch, wenn es nicht in Anführungszeichen $1steht (z. B. "hey x"), wird die Shell dies sehen x = x, sodass diese Konstruktion immer noch nicht sicher ist.

Der Zweck der x = xPrüfung besteht darin, festzustellen, ob eine Variable leer ist. Eine gebräuchlichere Methode hierfür ist die Verwendung von Anführungszeichen:

if [ "$1" = "" ]; then

Bash Test Betreiber -zund -nkann auch verwendet werden, aber sie sind weniger tragbar auf andere Arten von Muscheln. 1

Der Grund für die Anführungszeichen oder das x$1ist, dass die linke Seite nicht zu nichts erweitert wird, was ein syntaktischer Fehler wäre:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. Eigentlich testkann es ein eigenständiges Dienstprogramm sein, aber die meisten Shells implementieren es als eingebautes. Überprüfen Sie den Unterschied zwischen which testund type test. Unter GNU / Linux wird man testbehauptet, auf das eingebaute zu verweisen, aber wenn Sie (z. B.) aufrufen /usr/bin/test, scheint dieses Dienstprogramm die in der Manpage dokumentierten Funktionen zu implementieren, einschließlich -zund -n.

Goldlöckchen
quelle
1
[ x$1 = x ]wird auch als wahr ausgewertet, wenn dies $1beispielsweise der Fall ist " -o x". Versuchen Sie es sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]ist falsch und macht keinen Sinn.
Stéphane Chazelas
@ StéphaneChazelas Danke SC - bearbeitet (2. Abs.).
Goldlöckchen
Sie brauchen es nicht ifzu benutzen test, Sie können es vor &&, ||nach whileoder untersuchen das Ergebnis mit$?
Jasen
8
[ x$1 = x ]

Macht nur Sinn in zsh. Das vergleicht die Verkettung von xmit dem ersten Argument des Skripts x. Der [Befehl gibt also true zurück, wenn $1leer oder nicht angegeben.

[ $1 = "" ]

Wäre das nicht funktionieren , weil, in , zshwenn eine leeren Variable wird nicht in der Liste Kontext zitiert, es überhaupt statt einem leeren Argument ohne Argument erweitert, so dass , wenn $1waren nicht gesetzt oder leer, das [würde Befehl nur als Argument erhalten [, =die leeren Zeichenfolge und ]woraus es keinen Sinn machen konnte. [ -z "$1" ]oder [ "$1" = "" ]wäre aber OK wie in POSIX-Shells.

In Bourne-ähnlichen / POSIX-Shells [ x$1 = x ]macht das keinen Sinn. Das ist der split + glob-Operator, der irgendwie auf die Verkettung xund das erste Argument des Skripts angewendet wird, in der Hoffnung, dass das Ergebnis und =und xund ]einen gültigen Testausdruck für den [Befehl bilden.

Zum Beispiel, wenn das Skript eine übergeben wurde " = x -o x ="Argument, [würde diese Argumente erhalten: [, x, =, x, -o, x, =, x, ], die [als Vergleich würden verstehen , xmit xund xmit xund true zurück.

Wenn $1waren "* *", dann wäre die Schale an denen passiert [die Liste der Dateien im aktuellen Verzeichnis , dessen Namen beginnt mit dem Befehl x(Glob Erweiterung der x*), dann ist die Liste der nicht versteckten Dateien (Erweiterung *) ... , die [unwahrscheinlich ist in der Lage sein , irgendeinen Sinn machen aus. Die einzigen Fälle, in denen dies sinnvoll wäre, sind Fälle, in denen $1keine Platzhalter oder Leerzeichen enthalten sind.

Was Sie jetzt manchmal finden, ist Code wie:

[ "x$1" = x ]

Dies wird verwendet, um zu testen, ob $1leer oder nicht gesetzt ist.

Der normale Weg, auf eine leere oder nicht gesetzte Variable zu testen, ist:

[ -z "$1" ]

Aber das nicht für einige Werte von $1wie =in einigen (nicht-POSIX) [Implementierungen wie das Builtin man in dem Bourne - Shell wie gefunden /bin/shauf Solaris 10 und vor oder einigen alten Versionen dash(bis 0.5.4) oder den shvon einigen BSDs.

Das liegt daran [sieht [, -z, =, ]und beschwert sich über Argumente des fehlenden =Binäroperators statt es zu verstehen , wie der -zunäre Operator auf die angelegte =Zeichenfolge.

Ebenso [ "$1" = "" ]scheitert bei einigen Implementierungen an [if $1is !oder (.

In diesen Shell / [Implementierungen:

[ "x$1" = x ]

ist immer ein gültiger Test, unabhängig vom Wert von $1.

[ "" = "$1" ]

und:

[ -z "${1:+x}" ]

und

case $1 in "") ...; esac

Wenn Sie sicherstellen möchten, dass kein Argument angegeben wird, gehen Sie wie folgt vor:

[ "$#" -eq 0 ]

Das heißt, Sie überprüfen die Anzahl der an das Skript übergebenen Argumente.

Beachten Sie, dass heute [ -z "$var" ]deutlich von POSIX spezifiziert und kann nicht umhin , in konformen [Implementierungen (und bash‚s [ist und seit Jahrzehnten). Sie sollten sich also in POSIX sh oder bashSkripten darauf verlassen können.

Stéphane Chazelas
quelle
0

x$1verkettet zwei Zeichenketten xund $1wenn $ 1 leer ist, ist x $ 1 gleich x, und [x $ 1 = x] ist als Ergebnis wahr. x = ywird zum Vergleichen der Zeichenfolge in sh verwendet

harish.venkat
quelle
2
Nein x$1wird nicht in Anführungszeichen gesetzt, daher wird das Teilen und Verschieben dieser Elemente ausgeführt.
Stéphane Chazelas
0

[ x$1 = x ]ist wahr, wenn $1nicht gesetzt / null / leer ist oder nicht.
Versuchen Sie sich mit:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
und
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"

xx4h
quelle
1
[ x$1 = x ]Dies gilt auch, wenn dies $1beispielsweise der Fall ist " -o x". Versuchen Sie es sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]ist falsch und macht keinen Sinn.
Stéphane Chazelas