Inspiriert von dieser aktuellen Frage :
bash$ a=(1 2 3)
bash$ echo $a
1
aber
zsh% a=(1 2 3)
zsh% echo $a
1 2 3
zsh% printf '%s\n' $a
1
2
3
(Der letzte Teil zeigt, dass das Array in separate Argumente erweitert wird, die äquivalent zu "${a[@]}"
und nicht sind. "${a[*]}"
)
Das Bash-Verhalten (das mit ksh übereinstimmt) ist äußerst kontraintuitiv. Wie ist "nur erstes Element" eine vernünftige Reaktion auf "diese Array-Variable erweitern"?
In anderen Bereichen, in denen zsh divergiert, liegen ksh und bash näher an der ursprünglichen Bourne-Shell. Bourne hatte jedoch keine benutzerdefinierten Array-Variablen.
Warum hat Bash diese seltsame Entscheidung getroffen? Wenn es ksh kopierte, warum traf ksh diese seltsame Entscheidung?
Fortsetzung nach einer langen Reihe von Kommentaren:
Dies sollte keine Frage der Kritik oder des Lobes von zsh sein. zsh ist nichts anderes als ein leicht zugängliches Beispiel dafür, wie Dinge anders gemacht worden sein könnten .
Eine der Möglichkeiten, eine Entwurfsentscheidung zu erklären, ist die Abwärtskompatibilität. Und Abwärtskompatibilität ist keine Meinung. Es ist eine objektive Tatsache.
Wenn Sie ein Skript anzeigen können (ein vollständiges Skript , kein Auszug außerhalb des Kontexts), das sich in der Bourne-Shell auf bekannte Weise verhält (dh nicht nur mit einem Syntaxfehler bombardiert) und sich in der hypothetischen "Korn-Shell" anders verhält mit voller $ array Erweiterung ", dann gewinnen Sie! Es ist ein Problem mit der Abwärtskompatibilität.
Ein solches Skript wurde nicht angegeben. Dies ist nicht einer:
a=(1 2 3)
printf '%s\n' $a
weil es ein Syntaxfehler in der Bourne-Shell ist. Wenn Sie einem früheren Syntaxfehler eine neue Bedeutung geben, können Sie neue Funktionen erstellen und gleichzeitig die Abwärtskompatibilität beibehalten.
Soweit ich das beurteilen kann, führt die Tatsache, dass a=(...)
es sich ursprünglich um einen Syntaxfehler handelte, zu einer sauberen Trennung zwischen Skripten, die Arrays verwenden (versuchen) und solchen, die dies nicht tun. In der ersten Kategorie kann die Abwärtskompatibilität nicht als Grund für irgendetwas herangezogen werden, da diese Skripte ohnehin nicht in der alten Shell ausgeführt würden. In der zweiten Kategorie gilt die Abwärtskompatibilität unabhängig von den Erweiterungsregeln für Arrayvariablen, da keine zu erweiternden Arrays vorhanden sind!
Dies ist kein Beweis, da ich mich teilweise auf die Intuition verlasse, um zu entscheiden, dass es keine Möglichkeit gibt, ein Array ohne ein Skript zu schmuggeln, =(
und daher kein Skript existiert, das inkompatibles Verhalten aufweisen würde. Das Schöne an einer Behauptung der Nichtexistenz ist, dass Sie nur ein Gegenbeispiel zeigen müssen, um sie zu beenden.
Die a=$@
Sache, die in den Kommentaren angesprochen wurde, scheint zu einer Erklärung beizutragen. Wenn es eine Array-Variable erstellt, a
dann dieses Skript:
a=$@
printf '%s\n' $a
sollte den Unterschied zeigen. In meinen Tests passiert das jedoch nicht. Alle Muscheln (Erbstück sh, modernes ksh, bash und zsh) scheinen die erste Zeile auf die gleiche Weise zu behandeln. a
ist kein Array, sondern nur eine Zeichenfolge mit Leerzeichen. (zsh divergiert in der zweiten Zeile, weil es keine Wortteilung für den Wert von macht $a
, aber das hat nichts mit Array-Variablen zu tun)
a
ein Array in zsh enthalten könnte, warum in a=$@
, $a
ist eine Zeichenfolge?
=
Zeichen eine linke Klammer steht . a=($@)
kopiert das Array als Array.
a=(1 2 3); printf '%s\n' $a
konnte nicht mit 'b = $ a' kopiert werden, ist das nicht seltsam? In yash wird das Array kopiert b=$a
.
${array[0]}
möglicherweise nicht vorhanden, insbesondere bei assoziativen Arrays.