
Ich lese das Bash-Skript und verstehe nicht, was da vor sich geht.
#!/bin/sh
[ x$1 = x ]
Was passiert in der zweiten Zeile und was [ x$1 = x ]
bedeutet das?
Antwort1
Damit wird geprüft, ob das $1
leer ist, obwohl es in Anführungszeichen gesetzt werden sollte (identisch mit [ -z "$1" ]
). Einige sehr alte Shells konnten leere Zeichenfolgen nicht richtig verarbeiten, daher übernahmen die Autoren portabler Skripte diese Art der Prüfung. Das ist seit Jahrzehnten nicht mehr nötig, aber die Leute machen es immer noch so, weil die Leute es immer noch so machen.
Antwort2
Eckige Klammern kennzeichnen eineprüfen, also [ x$1 = x]
ohne if
oder etwas ähnliches ist bedeutungslos, obwohl syntaktisch ok.
Es soll als „true“ ausgewertet werden, wenn x$1
es zu erweitert wird x
, und andernfalls als „false“, da es aber nicht in Anführungszeichen steht und $1
die Shell beispielsweise „hey x“ sieht x = x
, ist diese Konstruktion trotzdem nicht sicher.
Der Zweck der x = x
Prüfung besteht darin, festzustellen, ob eine Variable leer ist. Eine gängigere Methode hierfür wäre die Verwendung von Anführungszeichen:
if [ "$1" = "" ]; then
Bash-Testoperatoren können -z
ebenfalls -n
verwendet werden, sind aber weniger auf andere Shell-Typen portierbar. 1
Der Grund für die Anführungszeichen bzw. das x$1
besteht darin, dass die linke Seite nicht ins Leere laufen soll, was ein syntaktischer Fehler wäre:
if [ = x ] # No good!
if [ "" = "" ] # Okay.
if [ x = x ] # Also okay.
1. Eigentlich test
kann es ein eigenständiges Dienstprogramm sein, aber die meisten Shells implementieren es als integriertes Dienstprogramm. Überprüfen Sie den Unterschied zwischen which test
und type test
. Unter GNU/Linux man test
wird behauptet, sich auf das integrierte Dienstprogramm zu beziehen, aber wenn Sie (zB) aufrufen /usr/bin/test
, scheint dieses Dienstprogramm die in der Manpage dokumentierten Funktionen zu implementieren, einschließlich -z
und -n
.
Antwort3
[ x$1 = x ]
Macht nur in Sinn zsh
. Dabei wird die Verkettung von x
mit dem ersten Argument des Skripts mit verglichen x
. Der [
Befehl gibt also true zurück, wenn $1
leer ist oder nicht angegeben wurde.
[ $1 = "" ]
Würde nicht funktionieren, weil zsh
eine leere Variable, wenn sie in Listenkontexten nicht in Anführungszeichen gesetzt ist, zu gar keinem Argument anstatt zu einem leeren Argument erweitert wird. Wenn sie also $1
nicht gesetzt oder leer wäre, [
würde der Befehl als Argumente nur [
, =
, den leeren String und erhalten ]
, mit dem er keinen Sinn erkennen könnte. [ -z "$1" ]
Oder [ "$1" = "" ]
wäre OK, wie in POSIX-Shells.
In Bourne-ähnlichen/POSIX-Shells [ x$1 = x ]
ergibt das keinen Sinn. Das ist der Split+Glob-Operator, der irgendwie auf die Verkettung von x
und dem ersten Argument des Skripts angewendet wird, in der Hoffnung, dass das Ergebnis und =
und x
, und ]
einen gültigen Testausdruck für den Befehl ergeben [
.
Wenn dem Skript beispielsweise ein " = x -o x ="
Argument übergeben würde, [
würde es diese Argumente erhalten: [
, x
, =
, x
, -o
, x
, =
, x
, ]
, was als Vergleich mit und mit [
verstanden würde und „true“ zurückgeben würde.x
x
x
x
Wenn , würde die Shell dem Befehl die Liste der Dateien im aktuellen Verzeichnis übergeben, deren Name mit (der Glob-Erweiterung von ) beginnt, dann die Liste der nicht versteckten Dateien (Erweiterung ) …, was wahrscheinlich keinen Sinn ergibt. Die einzigen Fälle, in denen dies etwas Sinnvolles bewirken würde, sind, wenn $1
keine Platzhalter oder Leerzeichen enthalten sind."* *"
[
x
x*
*
[
$1
Manchmal findet man Code wie den folgenden:
[ "x$1" = x ]
Dies wird verwendet, um zu testen, ob $1
es leer oder nicht gesetzt ist.
Die normale Vorgehensweise zum Testen, ob eine Variable leer oder nicht gesetzt ist, ist:
[ -z "$1" ]
Dies schlägt jedoch bei einigen Werten fehl, $1
beispielsweise =
bei einigen (nicht-POSIX-) [
Implementierungen, beispielsweise bei der integrierten in der Bourne-Shell, wie sie /bin/sh
unter Solaris 10 und früher oder einigen alten Versionen von dash
(bis 0.5.4) oder sh
einigen BSDs zu finden ist.
Das liegt daran, dass , , , [
sieht und sich über fehlende Argumente des binären Operators beschwert, anstatt ihn als den auf die Zeichenfolge angewendeten unären Operator zu verstehen .[
-z
=
]
=
-z
=
Ebenso [ "$1" = "" ]
schlägt bei einigen Implementierungen von [
if $1
is !
oder fehl (
.
In diesen Shell/ [
Implementierungen:
[ "x$1" = x ]
ist immer ein gültiger Test, unabhängig vom Wert von $1
. Das gilt auch für:
[ "" = "$1" ]
Und:
[ -z "${1:+x}" ]
Und
case $1 in "") ...; esac
Wenn Sie überprüfen möchten, dass kein Argument angegeben ist, gehen Sie natürlich wie folgt vor:
[ "$#" -eq 0 ]
Das heißt, Sie überprüfen die Anzahl der an das Skript übergebenen Argumente.
Beachten Sie, dass heutzutage von POSIX eindeutig spezifiziert ist und in konformen Implementierungen [ -z "$var" ]
nicht fehlschlagen kann (und dies ist seit Jahrzehnten der Fall). Sie sollten sich also in POSIX-sh oder -Skripten darauf verlassen können.[
bash
[
bash
Antwort4
[ x$1 = x ]
ist wahr, wenn $1
nicht gesetzt/null/leer ist oder nicht.
Probieren Sie es selbst mit:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
und
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"