Pourquoi n'y a-t-il pas de ;
caractère après do
les boucles shell lorsqu'il est écrit sur une seule ligne?
Voici ce que je veux dire. Lorsqu'elle est écrite sur plusieurs lignes, une for
boucle ressemble à:
$ for i in $(jot 2)
> do
> echo $i
> done
Et sur une seule ligne:
$ for i in $(jot 2); do echo $i; done
Toutes les lignes réduites obtiennent un ;
après elles, sauf la do
ligne, et si vous incluez le ;
, c'est une erreur. Quelqu'un probablement beaucoup plus intelligent que moi a décidé que c'était la bonne chose à faire pour une raison, mais je ne peux pas comprendre quelle est la raison. Cela me semble incohérent.
La même chose avec les while
boucles aussi.
$ while something
> do
> anotherthing
> done
$ while something; do anotherthing; done
while
/for
non plus.Réponses:
Telle est la syntaxe de la commande. Voir commandes composées
Notez spécifiquement:
do commands
La plupart des gens mettent le
do
etcommands
sur une ligne distincte pour permettre une meilleure lisibilité mais ce n'est pas nécessaire, vous pouvez écrire:Je sais que cette question concerne spécifiquement le shell et je l'ai lié au manuel bash. Ce n'est pas écrit de cette façon dans le manuel du shell, mais c'est écrit de cette façon dans un article écrit par Stephen Bourne pour le magazine byte.
Stephen dit:
la source
for i in thing; do; something; done
. Bien qu'un saut de ligne soit autorisé, un point-virgule n'est pas autorisé.something
est le sujet et s'ydo
applique. Tout comme dans la structure des phrases en anglais.while
syntaxe), vous avez donc besoin de quelque chose pour différencier les commandes de condition des commandes de corps de boucle. Lesdo
séparer est probablement ce qui semblait tout simplement le plus approprié.Je ne sais pas quelle est la raison d'origine de cette syntaxe, mais considérons le fait que les
while
boucles peuvent prendre plusieurs commandes dans la section condition, par exempleIci, le
do
mot-clé est nécessaire pour distinguer la section condition et le corps principal de la boucle.do
est un mot-clé commewhile
,if
etthen
(etdone
), et il semble être en ligne avec les autres qu'il ne nécessite pas de point-virgule ou de retour à la ligne mais apparaît immédiatement avant une commande.L'alternative (généralisée à
if
etwhile
) aurait l'air un peu moche, nous aurions besoin d'écrire par exempleLa syntaxe des
for
boucles est similaire.la source
La syntaxe du shell est basée sur un préfixe. Il a des clauses introduites par des mots clés spéciaux. Certaines clauses doivent aller de pair.
Une
while
boucle est constituée d'une ou plusieurs commandes de test:et par une ou plusieurs commandes de corps:
Quelque chose doit dire au shell qu'une boucle while commence. C'est le but du
while
mot:Mais alors, les choses sont ambiguës. Quelle commande est le début du corps? Quelque chose doit l'indiquer, et c'est ce que fait le
do
préfixe:et, enfin, quelque chose doit indiquer que le dernier corps a été vu; un mot
done
- clé spécial fait cela.Ces mots clés shell ne nécessitent pas de séparation par point-virgule, même sur la même ligne. Par exemple, si vous fermez plusieurs boucles imbriquées, vous pouvez simplement en avoir
done done done ...
.Au lieu de cela, le point-virgule est entre
... test ; body ...
s'ils sont sur la même ligne. Ce point-virgule est compris comme un terminateur: il appartient autest
. Par conséquent, si undo
mot-clé est inséré entre eux, il doit aller entre le point-virgule etbody
. S'il était de l'autre côté du point-virgule, il serait mal intégré dans latest
syntaxe de la commande, plutôt que placé entre les commandes.La syntaxe du shell a été initialement conçue par Stephen Bourne et est inspirée d' Algol . Bourne aimait tellement Algol qu'il a utilisé beaucoup de macros C dans le code source du shell pour faire ressembler C à Algol. Vous pouvez parcourir les sources du shell datant de 1979 à partir de la version 7 Unix . Les macros sont en place
mac.h
et sont utilisées partout. Par exemple lesif
déclarations sont rendus commeIF
...ELSE
...ELIF
...FI
.la source
Je dirais que ce
do
n'est pas particulièrement spécial ici. Vous obtenez une erreur car;
vous ne pouvez pas démarrer une liste de commandes. Si c'était le cas, la première commande serait vide et la grammaire n'autorise pas les commandes vides (affectations de variables ou redirections sans commande, oui, mais absolument rien, non). Cela est vrai dans n'importe quel nombre d'endroits, partout où une liste de commandes est attendue:Même:
Dans tous ces endroits, une liste de commandes est attendue, et donc un interligne
;
est inattendu.la source
do
(etif
etc.)?La syntaxe est:
N'importe lequel des sauts de ligne, soit dans la liste des commandes, soit avant le "do" ou le "done" peut être remplacé par un ";".
Un retour à la ligne (mais pas un ";") est autorisé après le "faire" et avant le "dans", juste pour rendre les choses plus belles, mais cela n'aurait aucun sens d' exiger un retour à la ligne.
la source
if
est similaire avec ses mots-clés: c'est assez lisible quand les commandes sont courtes:la source
\n
aprèsdo
tout cela avait du sens (tant que vous ne pensez pas à ne pas pouvoir mettre un arbitraire\n
entre d'autres commandes et arguments).do
,then
,else
ne sont pas args - si elles étaient, vous ne seriez pas autorisé à utiliser un point - virgule devant eux. Ce sont des mots-clés shell (voirtype if then elif else fi
)Réponse courte, car elle est spécifiée par la grammaire du shell POSIX . Tout ce qui se trouve entre
do
etdone
est considéré comme un groupe d'instructions, tandis que le;
séparateur est séquentiel:De plus, si cela
;
était nécessaire, la norme l'indiquerait explicitement et incluraitsequential_sep
aprèsDo
.la source
Parce que do est un mot-clé et ce qui suit est essentiellement des paramètres. L'interprète Bash sait que plus suit. C'est similaire à la façon dont il n'y a pas de ';' en suivant le i dans la commande for. Vous pouvez réellement ajouter une nouvelle ligne après le i dans et taper le reste sur une nouvelle ligne et cela fonctionnera bien.
la source