Un motivo semplificata è l'esistenza di un carattere: space.
Le espansioni di parentesi graffe non elaborano spazi (non quotati).
Un {...}
elenco necessita di spazi (non quotati).
La risposta più dettagliata è come la shell analizza una riga di comando .
Il primo passo per analizzare (comprendere) una riga di comando è dividerlo in parti.
Queste parti (di solito chiamate parole o token) derivano dalla divisione di una riga di comando per ciascun meta-carattere dal collegamento :
- Suddivide il comando in token separati dal set fisso di meta-caratteri: SPAZIO, TAB, NEWLINE,;, (,), <,>, | e &. I tipi di token includono parole, parole chiave, redirector I / O e punti e virgola.
Meta-personaggi: spacetabenter;,<>|e &.
Dopo la divisione, le parole possono essere di un tipo (come compreso dalla shell):
- Comandi pre-ordini:
LC=ALL ...
- Comando
LC=ALL echo
- argomenti
LC=ALL echo "hello"
- reindirizzamento
LC=ALL echo "hello" >&2
Espansione del rinforzo
Solo se una "stringa di parentesi graffe" (senza spazi o meta-caratteri) è una singola parola (come descritto sopra) e non è quotata , è un candidato per "Espansione di parentesi graffe ". Ulteriori controlli vengono eseguiti in seguito sulla struttura interna.
Quindi, questo: si {ls,-l}
qualifica come "Espansione di parentesi graffe" per diventare ls -l
, come first word
o argument
(in bash, zsh è diverso).
$ {ls,-l} ### executes `ls -l`
$ echo {ls,-l} ### prints `ls -l`
Ma questo non: {ls ,-l}
. Bash si dividerà spacee analizzerà la riga come due parole: {ls
e ,-l}
che attiverà un command not found
(l'argomento ,-l}
è perso):
$ {ls ,-l}
bash: {ls: command not found
La tua linea: {ls;echo hi}
non diventerà una "espansione di parentesi graffe" a causa dei due meta-personaggi ;e space.
Sarà suddiviso in questi tre parti: {ls
nuovo comando: echo
hi}
. Comprendi che ;innesca l'inizio di un nuovo comando. Il comando {ls
non verrà trovato e il comando successivo stamperà hi}
:
$ {ls;echo hi}
bash: {ls: command not found
hi}
Se viene inserito dopo qualche altro comando, avvierà comunque un nuovo comando dopo il ;:
$ echo {ls;echo hi}
{ls
hi}
Elenco
Uno dei "comandi composti" è una "Lista Brace" (le mie parole): { list; }
.
Come puoi vedere, è definito con spazi e una chiusura ;
.
Gli spazi e ;sono necessari perché entrambi {
e }
sono " Parole riservate ".
E quindi, per essere riconosciuto come parole, deve essere circondato da meta-caratteri (quasi sempre:) space.
Come descritto al punto 2 della pagina collegata
- Controlla il primo token di ciascun comando per vedere se è ...., {, o (, quindi il comando è in realtà un comando composto.
Il tuo esempio: {ls;echo hi}
non è un elenco.
Ha bisogno di una chiusura ;e uno spazio (almeno) dopo {. L'ultimo }è definito dalla chiusura ;.
Questa è una lista { ls;echo hi; }
. E questo { ls;echo hi;}
è anche (meno usato, ma valido) (Grazie @choroba per l'aiuto).
$ { ls;echo hi; }
A-list-of-files
hi
Ma come argomento (la shell conosce la differenza) a un comando, genera un errore:
$ echo { ls;echo hi; }
bash: syntax error near unexpected token `}'
Ma fai attenzione a ciò che ritieni che la shell stia analizzando:
$ echo { ls;echo hi;
{ ls
hi
{
interpretato come un elenco di comandi se appare all'inizio di un comando e come espansione di parentesi graffe altrimenti, ma non ne sono sicuro.