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?
Das prüft, dass $1
leer 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.
[ x$1 = x ]
ist immer noch falsch,[ "x$1" = x ]
wäre aber für shells die ein problem haben wo$1
ist!
oder(
oder-n
....[ "" = "$1" ]
undcase $1 in "")
wäre auch ok.[ -z "$1" ]
und[ "$1" = "" ]
funktionieren immer noch nicht mit / bin / sh von Solaris 10, dem ersteren mit dash-0.5.4.[ "$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.Eckige Klammern kennzeichnen einen Test , daher ist
[ x$1 = x]
withoutif
oder ähnliches bedeutungslos, obwohl syntaktisch in Ordnung.Es soll als wahr gewertet werden, wenn es
x$1
erweitert wirdx
, und als falsch, wenn es nicht in Anführungszeichen$1
steht (z. B. "hey x"), wird die Shell dies sehenx = x
, sodass diese Konstruktion immer noch nicht sicher ist.Der Zweck der
x = x
Prüfung besteht darin, festzustellen, ob eine Variable leer ist. Eine gebräuchlichere Methode hierfür ist die Verwendung von Anführungszeichen:Bash Test Betreiber
-z
und-n
kann auch verwendet werden, aber sie sind weniger tragbar auf andere Arten von Muscheln. 1Der Grund für die Anführungszeichen oder das
x$1
ist, dass die linke Seite nicht zu nichts erweitert wird, was ein syntaktischer Fehler wäre:1. Eigentlich
test
kann es ein eigenständiges Dienstprogramm sein, aber die meisten Shells implementieren es als eingebautes. Überprüfen Sie den Unterschied zwischenwhich test
undtype test
. Unter GNU / Linux wirdman test
behauptet, 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-z
und-n
.quelle
[ x$1 = x ]
wird auch als wahr ausgewertet, wenn dies$1
beispielsweise der Fall ist" -o x"
. Versuchen Sie essh -xc '[ x$1 = x ] && echo yes' sh ' -o x'
.[ x$1 = x ]
ist falsch und macht keinen Sinn.if
zu benutzentest
, Sie können es vor&&
,||
nachwhile
oder untersuchen das Ergebnis mit$?
Macht nur Sinn in
zsh
. Das vergleicht die Verkettung vonx
mit dem ersten Argument des Skriptsx
. Der[
Befehl gibt also true zurück, wenn$1
leer oder nicht angegeben.Wäre das nicht funktionieren , weil, in ,
zsh
wenn eine leeren Variable wird nicht in der Liste Kontext zitiert, es überhaupt statt einem leeren Argument ohne Argument erweitert, so dass , wenn$1
waren 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 Verkettungx
und das erste Argument des Skripts angewendet wird, in der Hoffnung, dass das Ergebnis und=
undx
und]
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 ,x
mitx
undx
mitx
und true zurück.Wenn
$1
waren"* *"
, dann wäre die Schale an denen passiert[
die Liste der Dateien im aktuellen Verzeichnis , dessen Namen beginnt mit dem Befehlx
(Glob Erweiterung derx*
), 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$1
keine Platzhalter oder Leerzeichen enthalten sind.Was Sie jetzt manchmal finden, ist Code wie:
Dies wird verwendet, um zu testen, ob
$1
leer oder nicht gesetzt ist.Der normale Weg, auf eine leere oder nicht gesetzte Variable zu testen, ist:
Aber das nicht für einige Werte von
$1
wie=
in einigen (nicht-POSIX)[
Implementierungen wie das Builtin man in dem Bourne - Shell wie gefunden/bin/sh
auf Solaris 10 und vor oder einigen alten Versionendash
(bis 0.5.4) oder densh
von einigen BSDs.Das liegt daran
[
sieht[
,-z
,=
,]
und beschwert sich über Argumente des fehlenden=
Binäroperators statt es zu verstehen , wie der-z
unäre Operator auf die angelegte=
Zeichenfolge.Ebenso
[ "$1" = "" ]
scheitert bei einigen Implementierungen an[
if$1
is!
oder(
.In diesen Shell /
[
Implementierungen:ist immer ein gültiger Test, unabhängig vom Wert von
$1
.und:
und
Wenn Sie sicherstellen möchten, dass kein Argument angegeben wird, gehen Sie wie folgt vor:
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 (undbash
‚s[
ist und seit Jahrzehnten). Sie sollten sich also in POSIX sh oderbash
Skripten darauf verlassen können.quelle
x$1
verkettet zwei Zeichenkettenx
und$1
wenn $ 1 leer ist, ist x $ 1 gleich x, und [x $ 1 = x] ist als Ergebnis wahr.x = y
wird zum Vergleichen der Zeichenfolge in sh verwendetquelle
x$1
wird nicht in Anführungszeichen gesetzt, daher wird das Teilen und Verschieben dieser Elemente ausgeführt.[ x$1 = x ]
ist wahr, wenn$1
nicht 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"
quelle
[ x$1 = x ]
Dies gilt auch, wenn dies$1
beispielsweise der Fall ist" -o x"
. Versuchen Sie essh -xc '[ x$1 = x ] && echo yes' sh ' -o x'
.[ x$1 = x ]
ist falsch und macht keinen Sinn.