Die Inkonsistenz ist größtenteils auf historische Gründe zurückzuführen.
Die Verwendung von Klammern als bedingter Befehl erfolgte nach der Verwendung von Klammern in Platzhaltermustern. Also kam zu der Zeit schon [ -n foo ]
die Szene auf, [foo]
bedeutete schon "eine Datei, deren Name f
oder ist o
". Während in der Praxis nur wenige Verwendungen des Operators "Klammern" mit realistischen Verwendungen der Klammern in Platzhaltern in Konflikt geraten wären, haben die Autoren beschlossen, nicht zu riskieren, vorhandene Skripte durch Ändern der Syntax zu beschädigen. Diese Entwurfsauswahl erleichterte auch die Implementierung: Ursprünglich [
wurde sie als externer Befehl implementiert, was nicht möglich gewesen wäre, wenn der nachfolgende Speicherplatz [
optional gewesen wäre. (Moderne Systeme haben immer noch [
einen externen Befehl, aber fast alle modernen Shells haben ihn auch eingebaut.)
Aus ähnlichen Gründen ist Ihr "funktionierender" Code in den meisten Fällen tatsächlich falsch. $1
bedeutet nicht "der Wert von Parameter 1": Es bedeutet "den Wert von Parameter 1 nehmen, ihn in Leerzeichen (oder was auch immer der Wert von IFS
ist) in separate Wörter aufteilen und jedes Wort als Glob-Muster interpretieren". Die Art und Weise, wie „der Wert von Parameter 1“ geschrieben wird, erfordert doppelte Anführungszeichen : "$1"
. Siehe Wann ist eine doppelte Anführungszeichen erforderlich? für das Wesentliche. Sie müssen das nicht verstehen; Alles, woran Sie sich erinnern müssen, ist: Setzen"$foo"
"$(foo)"
Sie immer doppelte Anführungszeichen um Variablensubstitutionen und Befehlssubstitutionen . Somit:
if [ -n "$1" ]; then …
In bash, ksh und zsh, aber nicht in plain sh, können Sie auch doppelte Klammern verwenden. Einzelne Klammern [ … ]
werden wie ein gewöhnlicher Befehl analysiert (und sind in der Tat [
ein gewöhnlicher Befehl, wenn auch normalerweise eingebaut). Doppelte Klammern sind ein separates syntaktisches Konstrukt, und Sie können die doppelten Anführungszeichen die meiste Zeit weglassen.
if [[ -n $1 ]]; then …
Es gibt jedoch eine Ausnahme: Um [[ "$foo" = "$bar" ]]
zu testen, ob die beiden Variablen denselben Wert haben, sind doppelte Anführungszeichen erforderlich $bar
, andernfalls $bar
wird dies als Platzhaltermuster interpretiert. Anstatt sich an die Details zu erinnern, können Sie auch immer doppelte Anführungszeichen verwenden.