Las declaraciones en bucle se utilizan para obligar a un programa a ejecutar repetidamente una declaración. La instrucción ejecutada se denomina cuerpo del ciclo.
Los bucles se ejecutan hasta que el valor de una expresión de control es 0. La expresión de control puede ser cualquier tipo de datos escalares.
El lenguaje de shell también proporciona varias iteraciones o instrucciones de bucle. En este artículo, revisemos las declaraciones de bucle que proporciona bash usando algunos ejemplos.
Bash admite los siguientes tres tipos de declaraciones en bucle
- Para bucle
- Mientras bucle
- Hasta bucle
Este artículo es parte de la serie de tutoriales de Bash en curso.
Los bucles se pueden anidar. Al igual que cualquier otro lenguaje de programación, bash también admite la instrucción break para salir del bucle actual y la instrucción continue para reanudar la siguiente iteración de la instrucción del bucle.
Bash For Loop:primer método
Los bucles for se utilizan normalmente cuando se conoce el número de iteraciones antes de entrar en el bucle bash. Bash admite dos tipos de bucle for. La primera forma de bash for loop es:
for varname in list do commands ##Body of the loop done
En la sintaxis anterior:
- for, in, do y done son palabras clave
- Lista es cualquier lista que tiene una lista de elementos
- varname es cualquier nombre de variable Bash.
De esta forma, la instrucción for ejecuta el comando encerrado en un cuerpo, una vez para cada elemento de la lista. El elemento actual de la lista se almacenará en una variable "varname" cada vez que pase por el ciclo. Este varname se puede procesar en el cuerpo del ciclo. Esta lista puede ser una variable que contenga varias palabras separadas por espacios. Si falta la lista en la declaración for, entonces toma el parámetro posicional que se pasó al shell.
Ejemplo 1 de Bash For Loop. Descomprima todo el archivo Zip
El siguiente ejemplo busca la lista de archivos que coinciden con "*.zip*" en el directorio raíz, crea un nuevo directorio en la misma ubicación donde existe el archivo zip y descomprime el contenido del archivo zip.
# cat zip_unzip.sh #! /bin/bash # Find files which has .zip for file in `find /root -name "*.zip*" -type f` do # Skip the extension .zip dirname=`echo ${file} | awk -F'.' '{print $1}'` # Create the directory mkdir $dirname # Copy the zip file cp ${file} ${dirname} cd $dirname # Unzip the zip file from newly created directory unzip ${dirname}/$(echo ${file##/*/}) done
- En este ejemplo, el comando de búsqueda devuelve la lista de archivos, desde la cual cada archivo se procesará a través de un bucle.
- Para cada elemento, crea el directorio con el nombre del archivo zip, copia el archivo zip en el directorio recién creado y descomprime el archivo zip desde allí.
- La instrucción echo, echo ${file##/*/} solo le da el nombre del archivo, no la ruta.
# ./zip_unzip.sh Archive: /root/test2/test2.zip extracting: t1/p extracting: t1/q extracting: t1/r extracting: t1/s extracting: t1/t extracting: t1/u extracting: t1/v Archive: /root/test1/test1.zip extracting: t/a extracting: t/b extracting: t/c extracting: t/d extracting: t/e
Al igual que el bucle Bash, Awk también proporciona bucles for y while, como comentamos en nuestro artículo Awk While y For Loop.
Bash For Loop:segundo método
La segunda forma de bucle for es similar al bucle for en el lenguaje de programación 'C', que tiene tres expresiones (inicialización, condición y actualización).
for (( expr1; expr2; expr3 )) do commands done
- En la sintaxis del comando bash for anterior, antes de la primera iteración, se evalúa expr1. Esto generalmente se usa para inicializar variables para el ciclo.
- Todas las declaraciones entre do y done se ejecutan repetidamente hasta que el valor de expr2 sea VERDADERO.
- Después de cada iteración del bucle, se evalúa expr3. Esto generalmente se usa para incrementar un contador de bucle.
El siguiente ejemplo genera el número n de números aleatorios.
Bash para el ejemplo 2. Generar n números aleatorios
$ cat random.sh #! /bin/bash echo -e "How many random numbers you want to generate" read max for (( start = 1; start <= $max; start++ )) do echo -e $RANDOM done $ ./random.sh How many random numbers you want to generate 5 6119 27200 1998 12097 9181
En el fragmento de código anterior, el ciclo for genera el número aleatorio en el número máximo de veces. RANDOM es una función bash interna que devuelve un número entero aleatorio en cada invocación.
Golpe mientras bucle
Otra declaración de iteración que ofrece el lenguaje de programación shell es la declaración while.
Syntax: while expression do commands done
En la sintaxis del ciclo while anterior:
- while, do, done son palabras clave
- Expresión es cualquier expresión que devuelve un valor escalar
- La declaración while hace que se ejecute un bloque de código mientras una expresión condicional proporcionada es verdadera.
Bash While Ejemplo 3. Escribir contenidos en un archivo
El siguiente ejemplo lee los datos de la salida estándar y los escribe en un archivo.
$ cat writefile.sh #! /bin/bash echo -e "Enter absolute path of the file name you want to create" read file while read line do echo $line >> $file done $ sh writefile.sh Enter absolute path of the file name you want to create /tmp/a while for until $ cat /tmp/a while for until
El ejemplo anterior lee el nombre de archivo del usuario y lee las líneas de datos de stdin y agrega cada línea a un nombre de archivo dado. Cuando EOF ingresa, la lectura fallará, por lo que el ciclo termina ahí.
Si está escribiendo muchos scripts de bash, puede usar el editor de Vim como un IDE de Bash usando el complemento de soporte de bash de Vim como discutimos anteriormente.
Bash While Ejemplo 4. Lee el contenido de un archivo
En el ejemplo anterior, lee los datos de stdout y los escribe en un archivo. En este ejemplo, lee el archivo
contenido y lo escribe en una salida estándar.
$ cat read.sh #! /bin/bash echo -e "Enter absolute path of the file name you want to read" read file exec <$file # redirects stdin to a file while read line do echo $line done $ ./read.sh Enter absolute path of the file name you want to read /tmp/a while for until
En este ejemplo, obtiene el nombre del archivo para leer y, al usar exec, redirige la entrada estándar a un archivo. A partir de ese momento, todo el stdin proviene de ese archivo, en lugar del teclado. El comando de lectura lee la línea de la entrada estándar, por lo que mientras el bucle lee la entrada estándar, hasta que se produce el EOF.
Golpear hasta bucle
La declaración hasta es muy similar en sintaxis y función a la declaración mientras. La única diferencia real entre los dos es que la declaración hasta ejecuta su bloque de código mientras que su expresión condicional es falsa, y la declaración mientras ejecuta su bloque de código mientras su expresión condicional es verdadera.
syntax: until expression do commands #body of the loop done
En la sintaxis bash before anterior:
donde before, do, done son palabras clave
expresión cualquier expresión condicional
Bash hasta Ejemplo 5. Supervisar el archivo de registro
Este ejemplo monitorea el tamaño del archivo de registro, una vez que el tamaño del archivo de registro alcanza los 2000 bytes, toma la copia de ese archivo de registro.
$ cat monitor.sh file=/tmp/logfile until [ $(ls -l $file | awk '{print $5}') -gt 2000 ] do echo "Sleeping for next 5 seconds" sleep 5 done date=`date +%s` cp $file "$file-"$date.bak $ ./monitor.sh Sleeping for next 5 seconds Sleeping for next 5 seconds $ ls -l /tmp/logfile* -rw-r--r-- 1 sss sss 2010 Jun 24 12:29 logfile -rw-r--r-- 1 sss sss 2005 Jun 24 16:09 logfile-1277474574.bak
La declaración hasta continúa ejecutando el cuerpo del ciclo, hasta que la condición se vuelve verdadera. En este ejemplo, la condición es el tamaño del archivo superior a 2000 bytes, por lo que copia el archivo una vez que alcanza los 2000 bytes.
Además, asegúrese de consultar nuestros ejemplos anteriores de Bash Array.
Bash hasta el ejemplo 6. Esperando a que aparezca la máquina
Este ejemplo se usa para esperar hasta que la máquina se active antes de hacer un ssh a esa máquina. La declaración de bucle hasta que finaliza solo cuando el ping da las respuestas.
$ cat mac_wait.sh #! /bin/bash read -p "Enter IP Address:" ipadd echo $ipadd until ping -c 1 $ipadd do sleep 60; done ssh $ipadd $./mac_wait.sh Enter IP Address:192.143.2.10 PING 192.143.2.10 (192.143.2.10) 56(84) bytes of data. --- 192.143.2.10 ping statistics --- 1 packets transmitted, 0 received, 100% packet loss, time 0ms PING 192.143.2.10 (192.143.2.10) 56(84) bytes of data. 64 bytes from 192.143.2.10: icmp_seq=1 ttl=64 time=0.059 ms --- 192.143.2.10 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.059/0.059/0.059/0.000 ms The authenticity of host '192.143.2.10 (192.143.2.10)' can't be established. Are you sure you want to continue connecting (yes/no)? yes
Hasta que el bucle es muy útil en la línea de comandos, como una forma de esperar a que ocurran ciertos eventos.