Shell-Kuriosität

TCM

Well-Known Member
Hi,

kann jemand auf Anhieb Folgendes erklären?

Code:
# uname -sr
FreeBSD 10.1-RELEASE-p5
# /bin/sh
# for foo in ${nonexistent:-}; do echo "foo: $foo"; done
foo: 
# for foo in; do echo "foo: $foo"; done
#

# uname -sr
OpenBSD 5.5
# /bin/sh
# for foo in ${nonexistent:-}; do echo "foo: $foo"; done
# for foo in; do echo "foo: $foo"; done
#

Irgendwie steh ich auf dem Schlauch, warum ${nonexistent:-} was anderes sein soll als "nichts". $nonexistent ist dabei eine ungesetzte Variable.
 
${nonexistent:-} gibt etwas zurück, und zwar einen leeren String, einen String der Länge null. Das ist ein gültiges Argument. Dagegen hat »for foo in;« gar kein Argument, es ist eine abweisende Schleife.
Bei OpenBSD scheint das anders zu sein, das müßte man in der Manpage der Shell nachlesen.
 
Guter Tipp, es wird aber nur komischer dadurch:

Code:
# uname -sr
OpenBSD 5.5
# /bin/sh
# for foo in ${nonexistent:-}; do echo "foo: $foo"; done
# for foo in; do echo "foo: $foo"; done                  
# for foo in ""; do echo "foo: $foo"; done
foo: 
#

Also ist ${:-} bei FreeBSD ein expliziter leerer String, bei OpenBSD "nichts".

Vom Gefühl her scheint mir OpenBSD "korrekt" zu sein, denn ich habe ${nonexistent:-} ja nicht gequotet, also dürfte da IMHO kein leerer String stehen.
 
Es liegt am :-, damit erzwingst Du einen rückgabewert. Das ist an der Stelle ja überflüssig. Ich denke das ist ein Bug, aber einer der in der Praxis nicht relevant ist. Denn:

Code:
$ for foo in ${bar:-$baz}; do echo "foo: $foo"; done
$
 
Wenn dann $baz nicht gesetzt ist, schlägt set -u aber wieder an. Wenn sich das alles "sauber" verhalten würde, bräuchte ich den separaten Check nicht, den ich jetzt reingebaut hab.

Meine Scripte haben alle set -u gesetzt.
 
Nach der Interpretation von OpenBSDs Shell (das ist doch immer noch die pdksh, oder?) sind die Ausdrücke $nix und ${nix:-} äquivalent und damit der zweite völlig überflüssig. Die Bash macht es übrigens genauso.
Die Shell von FreeBSD finde ich hier nützlicher, denn es mag durchaus mal den Wunsch geben, auch ohne Quotes einen leeren String zu bekommen, z. B. um häßliche Schachtelungen von Quotes zu vermeiden. Soweit mein Bauchgefühl.
Aber die mangelhafte Portabilität ist natürlich ärgerlich.
 
Im Kontext von set -u sind sie eben nicht äquivalent. $nix bombt die Shell, ${nix:-} macht weiter. Ich hätte mir halt den zusätzlichen Check auf Inhalt vor oder in der for-Schleife sparen können, wenn die Schleife ohne Inhalt gar nicht durchlaufen würde.
 
Zurück
Oben