Die Wortaufteilung gilt nur für nicht zitierte Erweiterungen (Parametererweiterung, arithmetische Erweiterung und Befehlssubstitution) in modernen Bourne-ähnlichen Shells (in zsh, nur Befehlssubstitution, sofern Sie keinen Emulationsmodus verwenden).
Wenn Sie das tun:
args a :b
Wortaufteilung ist überhaupt nicht beteiligt.
Es ist die Shell-Analyse, die diese tokenisiert, feststellt, dass das erste nicht eines seiner Schlüsselwörter ist, und daher ist es ein einfacher Befehl mit 3 Argumenten : args, aund :b. Der Platz macht dort keinen Unterschied. Beachten Sie, dass es sich nicht nur um Leerzeichen, sondern auch um Tabulatoren und in einigen Shells (wie yashoder bash) um Zeichen handelt, die in Ihrem Gebietsschema als leer betrachtet werden (im Fall von bashnicht den Multibyte- Zeichen ) ¹.
Auch in dem Bourne - Shell , wo einzelnen Worte aufgespalten auch nicht notierten Argumente von Befehlen unabhängig davon angewandt , ob sie das Ergebnis der Erweiterungen waren oder nicht, die getan werden würde auf der Oberseite (lange nach) den tokenising und Syntax - Analyse.
In der Bourne-Shell
IFS=i
while bib=did edit foo
Das würde das nicht analysieren als:
"wh" "le b" "b=d" "d ed" "t foo"
Aber erst als whilemit einem einfachen Befehl und das editWort (wie es ist ein Argument , aber nicht das bid=didWort , das eine Zuordnung ist) dieser einfache Befehl würde weiter aufgeteilt in edund tso , dass der edBefehl mit den drei Argumenten ed, tund fooals die ausgeführt werden würde Zustand dieser whileSchleife.
Die Wortaufteilung ist nicht Teil der Syntaxanalyse. Es ist wie ein Operator, der implizit auf Argumente (auch in forSchleifenwörtern, Arrays und mit einigen Shell das Ziel von Umleitungen und einigen anderen Kontexten ) für die Teile von ihnen angewendet wird , die nicht in Anführungszeichen stehen. Was verwirrend ist, ist, dass es implizit gemacht wird . Sie tun es nicht cmd split($x), Sie tun es cmd $xund das split()( tatsächlichglob(split()) ) ist impliziert. In zshmüssen Sie es explizit für Parametererweiterungen anfordern ( split($x)ist $=xda ( $=sieht aus wie eine Schere)).
Nun zu Ihren Beispielen:
args(){ echo ["$*"];}
args a :b # three spaces
# [a::b]
aund :bArgumente argsmit dem ersten Zeichen verbunden $IFSdie gibt a::b(beachten Sie, dass es eine schlechte Idee, mit [...]hier , wie es ist ein Globbing Operator).
args(){ echo [$*];}
args a :b # three spaces
# [a b] # two spaces
$*(was enthält a::b) wird aufgeteilt in adie leere Zeichenfolge und b. So ist es:
echo '[a' '' 'b]'
args(){ echo ["$1"]["$2"]; }
args a :b # three spaces
# [a][:b]
Kein Wunder, da es keine Wortspaltung gibt.
args(){ echo [$1][$2]; }
args a :b # three spaces
# [a][ b]
Das ist wie:
echo '[a]' '[' 'b]'
as $2( :b) würde in die leere Zeichenfolge und aufgeteilt b.
Ein Fall, in dem Sie Abweichungen zwischen den Implementierungen feststellen, ist, wenn er $IFSleer ist.
Im:
set a b
IFS=
printf '<%s>\n' $*
In einigen Muscheln (heutzutage meistens) sehen Sie
<a>
<b>
Und nicht <ab>einmal "$*"würde sich erweitern ab. Diese Schalen trennen diese aund bPositionsparameter immer noch, und dies wurde in der neuesten Version des Standards als POSIX-Anforderung festgelegt.
Wenn du. .. getan hast:
set a b
IFS=
var="$*" # note that the behaviour for var=$* is unspecified
printf '<%s>\n' $var
Sie würden sehen, <ab>dass die Information, dass aund b2 separate Argumente waren, verloren ging, wenn sie zugewiesen wurde $var.
¹ Natürlich sind es nicht nur Leerzeichen, die Wörter abgrenzen. Es gibt auch spezielle Token in der Shell-Syntax, deren Liste vom Kontext abhängt. In den meisten Kontexten |, ||, &, ;, Newline <, >, >>... abgrenzen Worte. Zum ksh93Beispiel können Sie einen Befehl ohne Leerzeichen schreiben, wie:
while({([[(:)]])})&&((1||1))do(:);uname<&2|tee>(rev)file;done
IFS=:undx="foo :bar", inargs $x. Wie wäre die Reihenfolge hier? Zum Beispiel wird nach dem Tokenargsund dem$xIdentifizieren des letzteren das Token erweitert und erneut markiert.