Para bucles en zsh y bash

57

He notado que hay dos formas alternativas de construir bucles en zsh :

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

Ambos imprimen:

1
2
3

Mi pregunta es, ¿por qué las dos sintaxis? ¿Está $xiterando a través de un tipo diferente de objeto en cada uno de ellos?

¿ Bash hace una distinción similar?

Apéndice:

¿Por qué funciona lo siguiente ?:

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

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

pero este no?

#!/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
fuente
55
para el ejemplo que "no funciona", que es un estilo csh para loop, te faltan los paréntesis. for x ($d); do print $x; donefuncionará y coincidirá con la primera sintaxis que haya enumerado al comienzo de su pregunta.
Tim Kennedy el
1
Es TAN loco , que esas dos afirmaciones, de hecho, no "funcionan igual". ¡Literalmente no puedo entenderlo! Necesito fumar algo de lo que esos diseñadores de conchas fumaban ', en el pasado, jajaja.
alex grey
Cuidado, hay más en esta historia de lo que parece inicialmente. Los invito a revisar mi respuesta.
jasonleonhard
No vi a nadie más mencionarlo, pero ambas formas permiten la omisión de do / done: for i ({0..4..2}) for j ({a..c}) echo "($i,$j)"= {0,2,4}x{a,b,c}. Los punto y coma se aplican al bucle más externo y las redirecciones se aplican al más interno, y si necesita cambiar eso, solo necesita llaves: for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n= {1,...,9}*({0,2,4}x{a,b,c}). Por supuesto, puede combinar bucles con expansión zsh:for i ("("{0..4..2}","{a..c}")") echo $i
John P

Respuestas:

59

Varias formas de comandos complejos, como los bucles, tienen formas alternativas en zsh. Estas formas están inspiradas principalmente en el caparazón C , que era bastante común cuando zsh era joven pero ahora ha desaparecido. Estas formas alternativas actúan exactamente como las formas normales, son solo una sintaxis diferente. Son ligeramente más cortos, pero menos claros.

La forma estándar para el forcomando es for x in 1 2 3; do echo $x; done, y la forma estándar para el whilecomando es while test …; do somecommand; done. Ksh, bash y zsh tienen una forma alternativa de for:, for ((i = 0; i < 42; i++)); do somecommand; doneque imita los forbucles de lenguajes como Pascal o C, para enumerar enteros. Otras formas exóticas que existen en zsh son específicas de zsh (pero a menudo están inspiradas en csh).

Gilles 'SO- deja de ser malvado'
fuente
Muchas gracias @Guilles. Aunque todavía estoy un poco confundido. ¿Qué forma es la específica para zsh? Además, he agregado un ejemplo al final de mi OP donde no puedo encontrar la manera de traducir entre sintaxis. Si la diferencia es solo la sintaxis, ¿cómo debo arreglar el segundo script en el apéndice para que funcione?
Amelio Vazquez-Reina
3
@intrpc Ver mi respuesta actualizada. En cuanto a su último ejemplo, no funciona porque escribió for x $dy zsh espera lo que escribió ino (dónde escribió $d. Los signos de puntuación y las palabras reservadas no pueden provenir de una expansión variable, deben analizarse antes de que el shell pueda comenzar en las expansiones variables.
Gilles 'SO- deja de ser malvado'
@intrpc ambos son específicos de zsh. zsh fue diseñado específicamente para admitir la sintaxis bourne, korn y c-shell, ya que es un híbrido de los tres.
Tim Kennedy el
1
@pseyfert Funciona, pero no tiene ninguna ventaja sobre los formularios que muestro: es menos portátil que el for (( … ))formulario y usa mucha memoria si 3 es grande.
Gilles 'SO- deja de ser malvado'
1
@ alpha_989 En sintaxis sh-like, necesitas dodespués ));. Zsh también acepta otra sintaxis for ((…)); COMMANDdonde COMMANDes un solo comando. Por eso acepta for ((i = 1; i<100; i++)); ghi show $i | grep "log". Cuando ve donedespués de esto, se queja porque no había dofin. Consulte "Formularios alternativos para comandos complejos" en el manual .
Gilles 'SO- deja de ser malvado'