Notei que {
pode ser usado na expansão de chaves:
echo {1..8}
ou no agrupamento de comandos:
{ls;echo hi}
Como o bash sabe a diferença?
bash
shell-script
lovespring
fonte
fonte
{
interpretado como uma lista de comandos, se aparecer no início de um comando e como uma expansão de chave, caso contrário, mas não tenho certeza.{ls;echo hi}
não é legalbash
. Você precisa de um espaço após a chave de abertura e um ponto e vírgula antes da chave de fechamento.Respostas:
A razão simplificada é a existência de um caractere: space.
As expansões de chaves não processam espaços (sem aspas).
Uma
{...}
lista precisa de espaços (sem aspas).A resposta mais detalhada é como o shell analisa uma linha de comando .
O primeiro passo para analisar (entender) uma linha de comando é dividi-la 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 :
Meta-caracteres: spacetabenter;,<>|e &.
Após a divisão, as palavras podem ser de um tipo (como entendido pelo shell):
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
Expansão de cinta
Somente se uma "cadeia de chaves" (sem espaços ou metacaracteres) for uma única palavra (como descrita acima) e não for citada , ela será candidata a "expansão de chaves". Mais verificações são realizadas na estrutura interna posteriormente.
Assim, isto: se
{ls,-l}
qualifica como "expansão de chave" para se tornarls -l
, comofirst word
ouargument
(no bash, zsh é diferente).Mas isso não irá:
{ls ,-l}
. O Bash irá dividir spacee analisar a linha como duas palavras:{ls
e,-l}
que acionará acommand not found
(o argumento,-l}
está perdido):Sua linha:
{ls;echo hi}
não se tornará uma "expansão Brace" por causa dos dois meta-caracteres ;e space.Ele será dividido em este três partes:
{ls
novo comando:echo
hi}
. Entenda que o ;gatilho inicia o novo comando. O comando{ls
não será encontrado e o próximo comando será impressohi}
:Se for colocado após algum outro comando, iniciará um novo comando após o ;:
Lista
Um dos "comandos compostos" é uma "Lista Brace" (minhas palavras):
{ list; }
.Como você pode ver, é definido com espaços e um fechamento
;
.Os espaços e ;são necessários porque ambos
{
e}
são " Palavras Reservadas ".E, portanto, para ser reconhecido como palavras, deve estar cercado por meta-caracteres (quase sempre space:).
Conforme descrito no ponto 2 da página vinculada
Seu exemplo:
{ls;echo hi}
não é uma lista.Precisa de um fechamento ;e um espaço (pelo menos) depois {. O último }é definido pelo fechamento ;.
Esta é uma lista
{ ls;echo hi; }
. E isso{ ls;echo hi;}
também é (menos usado, mas válido) (Obrigado @choroba pela ajuda).Mas como argumento (o shell sabe a diferença) para um comando, ele dispara um erro:
Mas tenha cuidado com o que você acredita que o shell está analisando:
fonte
;
e}
.{ ls;}
funciona como o ponto-e-vírgula já é um meta-personagem.O bloco
{
é uma palavra-chave shell, portanto, deve ser separada da próxima palavra por espaço, enquanto na expansão de chaves, não deve haver espaço (se você precisar expandir a expansão de um espaço, será necessário escapá-lo:)echo {\ ,a}{b,c}
.Você pode usar a expansão entre chaves no início de um comando:
Porém, você não pode usá-lo para expandir para um bloco, pois a análise dos comandos de agrupamento ocorre antes das expansões:
fonte
Ele sabe verificando a sintaxe da linha de comando. Da mesma forma, sabe que, na expressão
echo echo
, o primeiro eco deve ser tratado como um comando e o segundo eco como um parâmetro do primeiro eco.No bash é muito simples, pois
{ cmd; }
deve ter espaços e ponto e vírgula. No entanto, por exemplo, no zsh, eles não são necessários, mas ainda analisando o contexto do{}
shell é capaz de dizer o que deve ser feito com seu conteúdo.Considere o seguinte:
Ambos retornam a data atual, mas
retorna
1 2 3
porque o shell sabe{}
em um argumento de comandoecho
, portanto deve ser expandido.fonte
{
seguido por espaço sem aspas não inicia a expansão de chaves no bash.{
. O espaço não citado não pode estar em qualquer lugar, porque o shell divide toda a linha de comando em espaços.Em primeiro lugar, a chave composta deve ser uma palavra por si só e a primeira palavra da linha de comando:
Em segundo lugar, chaves individuais não são especiais (como você pode ver acima). Aparelhos vazios também não são especiais:
Qualquer coisa sem vírgulas também é apenas ela mesma
Aqui é onde a ação começa.
Então, basicamente, para que a expansão entre chaves comece, precisamos de uma única palavra (não separada em campos no espaço em branco), dentro da qual ocorre pelo menos uma instância do
{...}
interior da qual ocorre pelo menos uma vírgula.Esta pode ser a primeira palavra na linha de comando, a propósito:
fonte