Ein vereinfachtes Grund ist die Existenz eines Zeichens: space.
Klammererweiterungen verarbeiten keine (nicht in Anführungszeichen gesetzten) Leerzeichen.
Eine {...}
Liste benötigt (nicht in Anführungszeichen gesetzte) Leerzeichen.
Die detailliertere Antwort lautet, wie die Shell eine Befehlszeile analysiert .
Der erste Schritt zum Parsen (Verstehen) einer Befehlszeile besteht darin, sie in Teile zu unterteilen.
Diese Teile (normalerweise als Wörter oder Token bezeichnet) ergeben sich aus der Unterteilung einer Befehlszeile an jedem Metazeichen aus dem Link :
- Teilt den Befehl in Token auf, die durch die festgelegten Metazeichen getrennt sind: SPACE, TAB, NEWLINE,;, (,), <,>, | und &. Zu den Tokentypen gehören Wörter, Schlüsselwörter, E / A-Umleitungen und Semikolons.
Metazeichen: spacetabenter;,<>|und &.
Nach dem Teilen können Wörter von einem Typ sein (wie von der Shell verstanden):
- Befehlsvorbelegungen:
LC=ALL ...
- Befehl
LC=ALL echo
- Argumente
LC=ALL echo "hello"
- Umleitung
LC=ALL echo "hello" >&2
Klammererweiterung
Nur wenn eine "geschweifte Klammer" (ohne Leerzeichen oder Metazeichen) ein einzelnes Wort ist (wie oben beschrieben) und nicht in Anführungszeichen steht , ist sie ein Kandidat für die "geschweifte Klammer". Weitere Überprüfungen der internen Struktur werden später durchgeführt.
Also: {ls,-l}
Qualifiziert sich als "Klammererweiterung", um ls -l
entweder als first word
oder argument
(in bash ist zsh anders) zu werden.
$ {ls,-l} ### executes `ls -l`
$ echo {ls,-l} ### prints `ls -l`
Aber das wird nicht: {ls ,-l}
. Bash teilt spacedie Zeile in zwei Wörter auf und parst sie: {ls
und ,-l}
das löst ein aus command not found
(das Argument ,-l}
geht verloren):
$ {ls ,-l}
bash: {ls: command not found
Ihre Zeile: {ls;echo hi}
wird aufgrund der beiden Metazeichen ;und nicht zu einer "Klammererweiterung" space.
Es wird in diese drei Teile unterteilt werden: {ls
neuen Befehl: echo
hi}
. Verstehen Sie, dass dies den ;Start eines neuen Befehls auslöst. Der Befehl {ls
wird nicht gefunden und der nächste Befehl wird ausgegeben hi}
:
$ {ls;echo hi}
bash: {ls: command not found
hi}
Wenn es nach einem anderen Befehl platziert wird, startet es trotzdem einen neuen Befehl nach dem ;:
$ echo {ls;echo hi}
{ls
hi}
Liste
Einer der „Verbindung Befehle“ ist eine „Brace List“ (meine Worte): { list; }
.
Wie Sie sehen, wird es mit Leerzeichen und einem Abschluss definiert ;
.
Die Leerzeichen und ;werden benötigt, da beide {
und }
"Reserved Words " sind.
Um als Wörter erkannt zu werden, müssen sie daher von Metazeichen umgeben sein (fast immer:) space.
Wie in Punkt 2 der verlinkten Seite beschrieben
- Überprüft das erste Token jedes Befehls, um festzustellen, ob es sich um ...., {oder (handelt. Der Befehl ist dann tatsächlich ein zusammengesetzter Befehl.
Ihr Beispiel: {ls;echo hi}
ist keine Liste.
Es braucht einen Schluss ;und ein Leerzeichen (mindestens) danach {. Der letzte }wird durch den Abschluss definiert ;.
Dies ist eine Liste { ls;echo hi; }
. Und das { ls;echo hi;}
ist auch (seltener verwendet, aber gültig) (Danke @choroba für die Hilfe).
$ { ls;echo hi; }
A-list-of-files
hi
Als Argument (die Shell kennt den Unterschied) für einen Befehl löst sie jedoch einen Fehler aus:
$ echo { ls;echo hi; }
bash: syntax error near unexpected token `}'
Aber seien Sie vorsichtig, wenn Sie glauben, dass die Shell analysiert:
$ echo { ls;echo hi;
{ ls
hi
{
als würde es als Befehlsliste interpretiert, wenn es zu Beginn eines Befehls erscheint, und als geschweifte Erweiterung, aber ich bin mir nicht sicher.