Pour les boucles en zsh et bash

57

J'ai remarqué qu'il existe deux manières de créer des boucles en zsh :

  1. for x (1 2 3); do echo $x; done
  2. for x in 1 2 3; do echo $x; done

Ils ont tous deux imprimer:

1
2
3

Ma question est, pourquoi les deux syntaxes? Est-ce que $xitérer à travers un type d'objet différent dans chacun d'eux?

Est -ce que bash faire une distinction similaire?

Addenda:

Pourquoi fonctionne ce qui suit ?:

#!/bin/zsh
a=1
b=2
c=5    

d=(a b c)    
for x in $d; do print $x;done

mais celui-ci ne le fait pas ?:

#!/bin/zsh
a=1
b=2
c=5

d=(a b c)    
# It complains with "parse error near `$d'"
for x $d; do print $x;done 
Amelio Vazquez-Reina
la source
5
pour l'exemple qui "ne fonctionne pas", qui est un style csh pour loop, il vous manque les parenthèses. for x ($d); do print $x; doneCela fonctionnera et correspondra à la première syntaxe que vous avez énumérée au début de votre question.
Tim Kennedy
1
Il est TELLEMENT fou que ces deux déclarations ne "fonctionnent pas de la même manière". Je ne peux littéralement pas comprendre la situation! J'ai besoin de fumer une partie de ce que ces concepteurs de coquillages fumaient », à l'époque, lol.
alex grey
Attention, cette histoire ne se résume pas à ce qu’elle semble au départ. Je vous invite à vérifier ma réponse.
jasonleonhard
Je n'ai vu personne d'autre le mentionner, mais les deux formes permettent l'omission de do / done: for i ({0..4..2}) for j ({a..c}) echo "($i,$j)"= {0,2,4}x{a,b,c}. Les points-virgules s'appliquent à la boucle la plus externe et les redirections, à la partie la plus intérieure. Si vous devez modifier cela, vous n'avez besoin que d'accolades: for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n= {1,...,9}*({0,2,4}x{a,b,c}). Bien sûr, vous pouvez combiner des boucles avec une extension zsh:for i ("("{0..4..2}","{a..c}")") echo $i
John P

Réponses:

59

Plusieurs formes de commandes complexes telles que les boucles ont des formes alternatives en zsh. Ces formes sont principalement inspirées par la coquille en C , qui était assez courante quand zsh était jeune mais a maintenant disparu. Ces formes alternatives fonctionnent exactement comme les formes normales, elles sont simplement une syntaxe différente. Ils sont légèrement plus courts, mais moins clairs.

Le formulaire standard pour la forcommande est for x in 1 2 3; do echo $x; done, et le formulaire standard pour la whilecommande est while test …; do somecommand; done. Ksh, bash et zsh ont une autre forme de for: for ((i = 0; i < 42; i++)); do somecommand; donequi imite les forboucles de langues comme Pascal ou C, pour énumèrent entiers. D'autres formes exotiques existant dans zsh sont spécifiques à zsh (mais sont souvent inspirées par csh).

Gilles, arrête de faire le mal
la source
Merci beaucoup @Guilles. Je suis toujours un peu confus cependant. A quelle forme est le spécifique zsh? De plus, j'ai ajouté un exemple à la fin de mon PO, où je ne sais pas comment traduire les syntaxes. Si la différence ne concerne que la syntaxe, comment dois-je corriger le deuxième script de l'addenda pour le faire fonctionner?
Amelio Vazquez-Reina
3
@intrpc Voir ma réponse mise à jour. Quant à votre dernier exemple, cela ne fonctionne pas parce que vous avez écrit for x $det compte zsh soit inou (où vous avez écrit $d. Les signes de ponctuation et les mots réservés ne peuvent pas provenir d'un développement de variable, ils doivent être analysés avant que le shell puisse démarrer sur les développements de variable.
Gilles 'SO- arrête d'être méchant'
@intrpc les deux sont spécifiques à zsh. zsh a été spécialement conçu pour prendre en charge la syntaxe bourne, korn et c-shell, car il s'agit d'un hybride des trois.
Tim Kennedy
1
@pseyfert Cela fonctionne, mais il n'a aucun avantage par rapport aux formulaires que je présente: il est moins portable que le for (( … ))formulaire et utilise beaucoup de mémoire si le nombre de pixels 3 est important.
Gilles 'SO- arrête d'être méchant'
1
@ alpha_989 Dans la syntaxe de type sh, il vous faut doaprès ));. Zsh accepte également une autre syntaxe for ((…)); COMMANDCOMMANDest une commande unique. C'est pourquoi il accepte for ((i = 1; i<100; i++)); ghi show $i | grep "log". Quand il voit doneaprès cela, il se plaint parce qu'il n'y avait pas dode fin. Voir «Autres formes de commandes complexes» dans le manuel .
Gilles, arrête d'être méchant. '