Um motivo simplificado é a existência de um caractere: space .
As expansões de chaves não processam espaços (não citados).
Uma lista {...}
precisa de espaços (não citados).
A resposta mais detalhada é como o shell analisa um linha de comando .
O primeiro passo para analisar (entender) uma linha de comando é dividi-lo em partes.
Essas partes (geralmente chamadas de palavras ou tokens) resultam da divisão de uma linha de comando em cada meta-caractere do link :
- Splits the command into tokens that are separated by the fixed set of meta-characters: SPACE, TAB, NEWLINE, ;, (, ), <, >, |, and &. Types of tokens include words, keywords, I/O redirectors, and semicolons.
Meta-caracteres: espaço aba entra ; , < > | e & .
Após a divisão, as palavras podem ser de um tipo (conforme entendido pelo shell):
- Pré-atribuições de comando:
LC=ALL ...
- Comando
LC=ALL echo
- Argumentos
LC=ALL echo "hello"
- Redirecionamento
LC=ALL echo "hello" >&2
Expansão de órtese
Somente se uma "string de chave" (sem espaços ou metacaracteres) for uma única palavra (como descrito acima) e não for citada , ela é candidata a "expansão de contraventamento". Mais verificações são realizadas na estrutura interna depois.
Assim, este: {ls,-l}
se qualifica como "Expansão de contraventamento" para se tornar ls -l
, como first word
ou argument
(no bash, zsh é diferente).
$ {ls,-l} ### executes 'ls -l'
$ echo {ls,-l} ### prints 'ls -l'
Mas isso não será: {ls ,-l}
. O Bash dividirá em espaço e analisará a linha como duas palavras: {ls
e ,-l}
, o que acionará um command not found
(o argumento ,-l}
é perdido):
$ {ls ,-l}
bash: {ls: command not found
Sua linha: {ls;echo hi}
não se tornará uma "expansão de contraventamento" devido aos dois metacaracteres ; e espaço .
Ele será dividido em três partes: {ls
new comando: echo
hi}
. Entenda que o ; aciona o início de um novo comando. O comando {ls
não será encontrado e o próximo comando exibirá hi}
:
$ {ls;echo hi}
bash: {ls: command not found
hi}
Se for colocado depois de algum outro comando, ele irá iniciar um novo comando após o ; :
$ echo {ls;echo hi}
{ls
hi}
Lista
Um dos "comandos compostos" é uma "Lista de Brace" (minhas palavras): { list; }
.
Como você pode ver, ele é definido com espaços e um fechamento ;
.
Os espaços e ; são necessários, porque {
e }
são "Reservados Palavras ".
E, portanto, para ser reconhecido como palavras, deve ser cercado por meta-caracteres (quase sempre: espaço ).
Conforme descrito no ponto 2 da página vinculada
- Checks the first token of each command to see if it is .... , {, or (, then the command is actually a compound command.
Seu exemplo: {ls;echo hi}
não é uma lista.
Ele precisa de um fechamento ; e um espaço (pelo menos) depois de {. O último } é definido pelo fechamento ; .
Esta é uma lista { ls;echo hi; }
. E esse { ls;echo hi;}
também é (menos comumente usado, mas válido) (Obrigado @choroba pela ajuda).
$ { ls;echo hi; }
A-list-of-files
hi
Mas como argumento (o shell sabe a diferença) para um comando, ele dispara um erro:
$ echo { ls;echo hi; }
bash: syntax error near unexpected token '}'
Mas tenha cuidado com o que você acredita que o shell está analisando:
$ echo { ls;echo hi;
{ ls
hi