Por que não existe um ;
caractere depois de do
loops de shell quando escrito em uma única linha?
Aqui está o que eu quero dizer. Quando escrito em várias linhas, um for
loop se parece com:
$ for i in $(jot 2)
> do
> echo $i
> done
E em uma única linha:
$ for i in $(jot 2); do echo $i; done
Todas as linhas recolhidas recebem um ;
depois delas, exceto a do
linha e, se você incluir a ;
, é um erro. Alguém provavelmente muito mais esperto do que eu, decidiu que isso era a coisa certa a se fazer por uma razão, mas não consigo descobrir qual é a razão. Parece inconsistente para mim.
O mesmo com while
loops também.
$ while something
> do
> anotherthing
> done
$ while something; do anotherthing; done
while
/for
também.Respostas:
Essa é a sintaxe do comando. Consulte Comandos compostos
Observe especificamente:
do commands
A maioria das pessoas coloca o
do
ecommands
em uma linha separada para facilitar a legibilidade, mas não é necessário; você pode escrever:Eu sei que esta pergunta é especificamente sobre shell e eu vinculei ao manual do bash. Não está escrito assim no manual do shell, mas sim em um artigo escrito por Stephen Bourne para a revista byte.
Stephen diz:
fonte
for i in thing; do; something; done
. Embora uma quebra de linha seja permitida, um ponto e vírgula não é permitido.something
assunto é edo
se aplica a ele. Assim como na estrutura das frases em inglês.while
sintaxe), então você precisa de algo para diferenciar os comandos da condição dos comandos do corpo do loop. Usardo
para separá-los é provavelmente o que parecia mais adequado.Não sei qual é o motivo original dessa sintaxe, mas vamos considerar o fato de que os
while
loops podem executar vários comandos na seção de condições, por exemplo,Aqui, a
do
palavra-chave é necessária para diferenciar a seção de condição e o corpo principal do loop.do
é uma palavra-chave comowhile
,if
ethen
(edone
), e parece estar alinhada com as outras que não requer ponto-e-vírgula ou nova linha após ela, mas aparece imediatamente antes de um comando.A alternativa (generalizada para
if
ewhile
) pareceria um pouco feia, precisaríamos escrever por exemploA sintaxe dos
for
loops é semelhante.fonte
A sintaxe do shell é baseada em prefixo. Possui cláusulas introduzidas por palavras-chave especiais. Certas cláusulas precisam seguir juntas.
Um
while
loop é formado por um ou mais comandos de teste:e por um ou mais comandos do corpo:
Algo precisa dizer ao shell que um loop while começa. Esse é o objetivo da
while
palavra:Mas então, as coisas são ambíguas. Qual comando é o começo do corpo? Algo tem que indicar isso, e é isso que o
do
prefixo faz:e, finalmente, algo tem que indicar que o último corpo foi visto; uma palavra-chave especial
done
faz isso.Essas palavras-chave shell não requerem separação de ponto e vírgula, mesmo na mesma linha. Por exemplo, se você fechar vários loops aninhados, poderá apenas ter
done done done ...
.Em vez disso, o ponto e vírgula é entre
... test ; body ...
se eles estiverem na mesma linha. Esse ponto-e-vírgula é entendido como um terminador: ele pertence aotest
. Portanto, se umado
palavra-chave é inserida entre eles, ela deve ir entre o ponto e vírgula ebody
. Se estivesse do outro lado do ponto e vírgula, seria incorretamente incorporado àtest
sintaxe do comando, em vez de ser colocado entre os comandos.A sintaxe do shell foi originalmente projetada por Stephen Bourne e é inspirada em Algol . Bourne amava tanto o Algol que usava muitas macros C no código-fonte do shell para fazer o C parecer com o Algol. Você pode procurar as fontes de shell datadas de 1979 na Versão 7 Unix . As macros estão inseridas
mac.h
e são usadas em todo o lugar. Por exemploif
declarações são processados comoIF
...ELSE
...ELIF
...FI
.fonte
Eu diria que isso
do
não é particularmente especial aqui. Você recebe um erro porque;
não pode iniciar uma lista de comandos. Se isso acontecesse, o primeiro comando ficaria vazio e a gramática não permitirá comandos vazios (atribuições de variáveis ou redirecionamentos sem um comando, sim, mas absolutamente nada, não). Isso ocorre em qualquer número de lugares, sempre que uma lista de comandos é esperada:Até:
Em todos esses lugares, é esperada uma lista de comandos e, portanto, uma liderança
;
é inesperada.fonte
do
(eif
etc)?A sintaxe é:
Qualquer uma das novas linhas, na lista de comandos ou antes de "do" ou "done", pode ser substituída por um ";".
Uma nova linha (mas não um ";") é permitida após o "fazer" e antes do "in", apenas para tornar as coisas mais agradáveis, mas não faria sentido exigir uma nova linha lá.
fonte
if
é semelhante às suas palavras-chave: isso é bastante legível quando os comandos são curtos:fonte
\n
depoisdo
que tudo fazia sentido (desde que você não pense em não poder colocar um arbitrário\n
entre outros comandos e argumentos).do
,then
,else
não são args - se fossem, você não seria permitido usar um ponto e vírgula antes deles. São palavras-chave do shell (vejatype if then elif else fi
)Resposta curta, porque isso é especificado pela gramática do shell POSIX . Qualquer coisa entre
do
edone
é considerado um grupo de instruções, enquanto;
é um separador sequencial:Além disso, se
;
fosse necessário, o padrão declararia isso explicitamente e incluiriasequential_sep
depoisDo
.fonte
Porque do é uma palavra-chave e o que se segue são essencialmente parâmetros. O intérprete do Bash sabe que mais se segue. É semelhante a como não há ';' seguindo o i no comando for. Você pode realmente adicionar uma nova linha após o i in e digitar o restante em uma nova linha e ela funcionará bem.
fonte