Das begann als Hack in der Bourne-Shell. In der Bourne-Shell wurde die IFS-Wortteilung (nach der Tokenisierung) für alle Wörter im Listenkontext (Befehlszeilenargumente oder die Wörter, auf denen sich die forSchleife befindet) durchgeführt. Wenn du hättest:
IFS=i var=file2.txt
edit file.txt $var
Diese zweite Linie in 3 Worten tokengekennzeichneten würde, $varerweitert werden würde, und Split + glob würde auf allen drei Worte geschehen, so würde Sie am Ende läuft edmit t, f, le.txt, f, le2.txtals Argumente.
Teile davon zu zitieren würde den Split + Glob verhindern. Die Bourne-Shell erinnerte sich anfangs daran, welche Zeichen in Anführungszeichen gesetzt wurden, indem sie das 8. Bit intern setzte (das änderte sich später, als Unix 8-Bit-sauber wurde, aber die Shell erinnerte sich noch an das angeführte Byte).
Beides $*und $@war die Verkettung der Positionsparameter mit dem Zwischenraum. Aber es gab eine spezielle Verarbeitung von $@Anführungszeichen. Wenn $1enthalten foo barund $2enthalten baz, "$@"würde erweitern auf:
foo bar baz
^^^^^^^ ^^^
(wobei das ^s oben angibt, für welches der Zeichen das 8. Bit gesetzt ist). Wobei das erste Leerzeichen in Anführungszeichen gesetzt wurde (wobei das 8. Bit gesetzt war), aber nicht das zweite (dasjenige, das zwischen den Wörtern hinzugefügt wurde).
Und es ist die IFS-Aufteilung, die sich um die Trennung der Argumente kümmert (vorausgesetzt, das Leerzeichen ist so, $IFSwie es standardmäßig ist). Das ist ähnlich wie $*bei seinem Vorgänger die Mashey-Shell (selbst basierend auf der Thomson-Shell, während die Bourne-Shell von Grund auf neu geschrieben wurde) erweitert wurde.
Das erklärt, warum in der Bourne-Shell anfangs "$@"die leere Zeichenfolge statt gar nichts erweitert wurde, wenn die Liste der Positionsparameter leer war (Sie mussten damit umgehen ${1+"$@"}), warum die leeren Positionsparameter nicht "$@"beibehalten wurden und warum nicht $IFSfunktioniert nicht, wenn das Leerzeichen nicht enthalten ist.
Die Absicht war, die Liste der Argumente wörtlich an einen anderen Befehl weitergeben zu können, aber das funktionierte nicht richtig für die leere Liste, für leere Elemente oder wenn $IFSkein Leerzeichen vorhanden war (die ersten beiden Probleme wurden in späteren Versionen behoben) ).
Die Korn-Shell (auf der die POSIX-Spezifikation basiert) hat dieses Verhalten auf verschiedene Arten geändert:
- Die IFS-Aufteilung wird nur für das Ergebnis nicht zitierter Erweiterungen durchgeführt (nicht für wörtliche Wörter wie
editoder file.txtim obigen Beispiel).
$*und $@sind mit dem ersten Zeichen verbunden ist $IFSoder , wenn Raum $IFSist leer , außer dass für eine zitiert "$@"wird , dass wie in dem Tischler Bourne - Shell unquoted und für eine zitiert , "$*"wenn IFSleer ist , die Positionsparameter werden ohne Trennangehängt.
- es zusätzliche Unterstützung für Arrays und mit
${array[@]} ${array[*]}erinnerte an Bourne $*und $@aber indice 0 anstelle von 1 beginnt und sparse (mehr wie assoziative Arrays) , die mittels $@nicht wirklich als KSH Array behandelt werden kann (vergleiche mit csh/ rc/ zsh/ fish/ yashwo $argv/ $*sind normale Arrays).
- Die leeren Elemente bleiben erhalten.
"$@"Wenn $#0 ist, wird statt der leeren Zeichenfolge jetzt nichts mehr angezeigt. Funktioniert, "$@"wenn $IFSkeine Leerzeichen enthalten sind, es sei denn, wenn IFSleer ist. Ein nicht in Anführungszeichen gesetztes $*Argument ohne Platzhalterzeichen wird zu einem Argument erweitert (wobei die Positionsparameter mit einem Leerzeichen verbunden werden), wenn $IFSes leer ist.
ksh93 hat die verbleibenden Probleme oben behoben. In ksh93 $*und wird $@die Liste der Positionsparameter erweitert, unabhängig vom Wert von getrennt $IFSund dann in Listenkontexten weiter aufgeteilt + globbed + geschweift-expandiert, $*verbunden mit dem ersten Byte (nicht dem Zeichen) von $IFS, "$@"in Listenkontexten wird die Liste erweitert von Positionsparametern, unabhängig vom Wert von $IFS. In Nicht-Listenkontext wie in var=$@, $@mit Raum verbunden , unabhängig vom Wert von $IFS.
bashDie Arrays sind nach den ksh-Arrays entworfen. Die Unterschiede sind:
- Keine Klammererweiterung bei nicht zitierter Erweiterung
- erstes Zeichen von
$IFSanstelle von für Byte
- Einige Unterschiede in der Groß- und Kleinschreibung, wie z. B. die Erweiterung von,
$*wenn im Kontext, in dem keine Liste vorhanden $IFSist, keine Anführungszeichen vorhanden sind, wenn leer.
Während die POSIX-Spezifikation früher ziemlich vage war, gibt sie jetzt mehr oder weniger das Bash-Verhalten an.
Es unterscheidet sich von normalen Arrays darin kshoder bashdarin:
- Indizes beginnen bei 1 anstelle von 0 (außer bei
"${@:0}"Includes $0(kein Positionsparameter, und bei Funktionen wird der Name der Funktion angegeben oder nicht, abhängig von der Shell und der Definition der Funktion)).
- Sie können Elemente nicht einzeln zuweisen
- Es ist nicht spärlich, Sie können Elemente nicht einzeln entfernen
shift kann verwendet werden.
In zshoder yashwo Arrays normale Arrays sind (nicht spärlich, Indizes beginnen wie in allen anderen Shells mit Ausnahme von ksh / bash bei einem), $*wird als normales Array behandelt. zshhat $argvals Alias dafür (aus Kompatibilitätsgründen mit csh). $*ist dasselbe wie $argvoder ${argv[*]}(Argumente, die mit dem ersten Zeichen von verbunden sind, $IFSaber dennoch in Listenkontexten getrennt sind). "$@"mag "${argv[@]}"oder "${*[@]}"}unterzieht sich der Korn-artigen Sonderverarbeitung.