Para loops no zsh e no bash

57

Notei que existem duas maneiras alternativas de criar loops no zsh :

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

Ambos imprimem:

1
2
3

Minha pergunta é: por que as duas sintaxes? Está $xiterando através de um tipo diferente de objeto em cada um deles?

O bash faz uma distinção semelhante?

Termo aditivo:

Por que o seguinte funciona ?:

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

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

mas este não ?:

#!/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
fonte
5
para o exemplo que "não funciona", que é um estilo csh para loop, você está perdendo os parênteses. for x ($d); do print $x; donefuncionará e corresponderá à primeira sintaxe que você enumerou no início da sua pergunta.
Tim Kennedy
1
É tão louco - que essas duas afirmações - de fato não funcionem da mesma forma. Eu literalmente não consigo entender! Eu preciso fumar um pouco do que aqueles designers de conchas estavam fumando ', antigamente, lol.
Alex Gray
Cuidado, há mais nessa história do que parece inicialmente. Convido você a verificar minha resposta.
jasonleonhard
Não vi mais ninguém mencioná-lo, mas ambas as formas permitem a omissão de do / done: for i ({0..4..2}) for j ({a..c}) echo "($i,$j)"= {0,2,4}x{a,b,c}. Os pontos e vírgulas se aplicam ao loop mais externo e os redirecionamentos se aplicam ao mais interno, e se você precisar alterar isso, precisará apenas de chaves: for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n= {1,...,9}*({0,2,4}x{a,b,c}). Claro que você pode combinar laços com a expansão zsh:for i ("("{0..4..2}","{a..c}")") echo $i
John P

Respostas:

58

Várias formas de comandos complexos, como loops, têm formas alternativas no zsh. Essas formas são principalmente inspiradas no shell C , que era bastante comum quando o zsh era jovem, mas agora desapareceu. Essas formas alternativas agem exatamente como as formas normais, são apenas uma sintaxe diferente. Eles são um pouco mais curtos, mas menos claros.

O formulário padrão para o forcomando é for x in 1 2 3; do echo $x; donee o formulário padrão para o whilecomando é while test …; do somecommand; done. Ksh, festa e zsh tem uma forma alternativa de for: for ((i = 0; i < 42; i++)); do somecommand; done, que imita os forlacetes de linguagens como Pascal ou C, para enumerar inteiros. Outras formas exóticas que existem no zsh são específicas do zsh (mas geralmente inspiradas no csh).

Gilles 'SO- parar de ser mau'
fonte
Muito obrigado @Guilles. Ainda estou um pouco confuso. Qual formulário é o específico zsh? Além disso, adicionei um exemplo no final do meu OP em que não consigo descobrir como traduzir entre sintaxes. Se a diferença for apenas sintaxe, como devo corrigir o segundo script no adendo para fazê-lo funcionar?
Amelio Vazquez-Reina
3
@intrpc Veja minha resposta atualizada. Quanto ao seu último exemplo, não funciona porque você escreveu for x $de o zsh espera inou (onde você escreveu $d. Os sinais de pontuação e as palavras reservadas não podem vir de uma expansão variável, eles precisam ser analisados ​​antes que o shell possa iniciar nas expansões variáveis.
Gilles 'SO- stop be evil'
@intrpc são ambos específicos do zsh. O zsh foi projetado especificamente para suportar as sintaxes bourne, korn e c-shell, pois é um híbrido dos três.
Tim Kennedy
1
@pseyfert Funciona, mas não tem nenhuma vantagem sobre os formulários que mostro: é menos portátil que o for (( … ))formulário e usa muita memória se 3 for grande.
Gilles 'SO- stop be evil'
1
@ alpha_989 Na sintaxe do tipo sh, você precisa dodepois ));. O Zsh também aceita outra sintaxe, na for ((…)); COMMANDqual COMMANDexiste um único comando. É por isso que aceita for ((i = 1; i<100; i++)); ghi show $i | grep "log". Quando vê donedepois disso, reclama porque não havia dofim. Consulte "Formulários alternativos para comandos complexos" no manual .
Gilles 'SO- stop be evil'