sintaxis de bucle for

sintaxis de bucle for

Por que

for i in {1..5}; do x="${i}" echo "$x"; done

no salida

1
2
3
4
5

?

¿Cuál es la forma correcta de hacer esto?

(Probadofor i in {1..5}; do x=$(i) echo "$x"; done

-bash: i: comando no encontrado

y otros)

Respuesta1

Respondiendo a su pregunta como se le preguntó

¿Por qué for i in {1..5}; do x="${i}" echo "$x"; doneno sale 1, 2, 3, 4, 5?

La razón tiene que ver con el orden en que se evalúan las operaciones durante la ejecución. Mira este comando

x="${i}" echo "$x"

Lo que esto hace es

  1. Sustituir variables por sus valores.
  2. Asignar un valor temporal a la variablex
  3. Ejecutar el comando

Entonces obtienes

  1. x=1 echo ""(o x=2 echo "", etc.)
  2. Mientras dure este comando, xse establece en el valor1
  3. El comando se ejecuta:echo ""

Es probable que haya querido decir que este comando son dos instrucciones: asignar un valor a xy generar su valor. Pero en la sintaxis del shell lo que escribiste fue un código perfectamente legal, por lo que el shell lo ejecutó sin objeciones.

Respuesta2

Solicitó respuestas a dos preguntas:

  1. Solicitó una explicación de por qué su código actual no produce el resultado esperado.

  2. Preguntó por la forma correcta de escribir su código para que produzca el resultado esperado.

Al observar su código, puedo ver dos posibles explicaciones de por qué escribió su código de la forma en que lo hizo:

  1. Puede haber alguna ligera confusión sobre elsintaxis de un bucle for.

  2. Puede haber una ligera confusión sobre el orden de evaluación en lo que se llama uncomando simple.

sintaxis de bucle for

En el primer caso, diría que falta un punto y coma después de la asignación de variable. Si desea escribir su bucle for en una sola línea, debe colocar un punto y coma después de cada comando en el cuerpo del bucle. Pruebe esto en su lugar:

for i in {1..5}; do x="${i}"; echo "$x"; done

Otra alternativa sería escribir el bucle for usando la sintaxis de varias líneas con nuevas líneas en lugar de punto y coma:

for i in {1..5}
do
x="${i}"
echo "${x}"
done

También puedes mezclar y combinar puntos y comas y nuevas líneas, por ejemplo:

for i in {1..5}; do
x="${i}"; echo "${x}"
done

evaluación de comandos simples

En el segundo caso, diría que probablemente haya asumido que la asignación de variable en el prólogo del comando (es decir, la x="$i"asignación) ocurre antes de la expansión de la variable en el cuerpo del comando (es decir, la expansión de ${x}in echo "${x}"). Pero en realidad este no es el caso. Para verificar esto podemos consultar la página enexpansión de comando simpleen el Manual de Bash o en elsubsección sobre comandos simplesen elEspecificación Posix. Ambas referencias incluyen el siguiente pasaje:

Un "comando simple" es una secuencia de asignaciones de variables y redirecciones opcionales, en cualquier secuencia, seguidas opcionalmente de palabras y redirecciones, terminadas por un operador de control.

Cuando se requiere ejecutar un comando simple dado (es decir, cuando cualquier construcción condicional como una lista AND-OR o unacasodeclaración no ha omitido el comando simple), las siguientes expansiones, asignaciones y redirecciones se realizarán desde el principio del texto del comando hasta el final:

  1. Las palabras que se reconocen como asignaciones variables o redirecciones segúnReglas gramaticales de Shellse guardan para su procesamiento en los pasos 3 y 4.

  2. Se ampliarán las palabras que no sean asignaciones variables o redirecciones. Si quedan campos después de su expansión, el primer campo se considerará el nombre del comando y los campos restantes serán los argumentos del comando.

  3. Las redirecciones se realizarán como se describe enRedirección.

  4. Cada asignación de variable se ampliará para la expansión de tilde, la expansión de parámetros, la sustitución de comandos, la expansión aritmética y la eliminación de comillas antes de asignar el valor.

Observe que el paso 2 es donde ocurre la expansión de variables en el comando, pero el paso 1 nos dice que las asignaciones de variables se guardan hasta los pasos 3 y 4. De ello se deduce que la expresión echo "${x}"se expande antes de que se realice echo ""la asignación . x="${i}"Esto explica por qué obtenía una salida vacía.

Para obtener más información sobre este tema, consulte las siguientes publicaciones:

Respuesta3

En zsh, se utiliza una tercera ${var::=value}forma de los ${var=value}operadores ${var:=value}de Bourne donde la asignación es incondicional (en lugar de solo si var está desarmado/vacío).

for i in {1..5}; do echo ${x::=$i}; done

O:

for i ({1..5}) echo ${x::=$i}

En bash:

set -o posix # so the value of x remains after eval returns
for i in {1..5}; do x=$i eval 'echo "$x"'; done

Es decir, debe $xhaber sido configurado en el momento de evaluar el código que contiene su expansión.

Para valores enteros decimales como aquí, también puedes hacer:

for i in {1..5}; do echo "$((x = i))"; done

O siempre puede usar el ${var:=value}operador Bourne después de haberlo configurado xen la cadena vacía.

for i in {1..5}; do x=; echo "${x:=$i}"; done

información relacionada