Cómo realizar un bucle, también conocido como diseñar un programa para que haga un trabajo repetitivo por usted
El bucle es una de las construcciones más fundamentales y poderosas en la informática, porque nos permite repetir un conjunto de comandos, tantas veces como queramos, en una lista de elementos de nuestra elección. Gran parte del pensamiento computacional implica tomar una tarea y resolverla de una manera que se pueda aplicar repetidamente a todas las demás tareas similares, y el ciclo for es cómo hacemos que la computadora haga ese trabajo repetitivo:
A diferencia de la mayoría del código que hemos escrito hasta ahora en el indicador interactivo, un bucle for no se ejecuta tan pronto como presionamos Enter:
Podemos escribir tantos comandos como queramos en el bloque entre las palabras clave do
y done
:
Solo hasta que lleguemos a done
, y presionemos Enter, el ciclo for hace su trabajo.
Esto es fundamentalmente diferente al comando y respuesta línea por línea que hemos experimentado hasta ahora en el indicador. Y presagia cómo estaremos programando más adelante: menos énfasis en ejecutar comandos con cada línea, y más énfasis en planificar la funcionalidad de un programa y luego ejecutarlo más tarde.
Sintaxis básica
La sintaxis de los bucles for
puede ser confusa, así que aquí hay algunos ejemplos básicos para preparar / actualizar su comprensión de ellos:
Aquí «una versión más elaborada usando variables:
Se puede usar una sustitución de comando para generar los elementos que recorre el bucle for
:
Si necesita leer una lista de líneas de un archivo, y estamos absolutamente seguros de que ninguna de las líneas contiene un espacio dentro de ellas:
Un ciclo de lectura mientras es una variación de lo anterior, pero es más seguro para leer líneas de un archivo:
Construyendo un bucle for básico
Empecemos desde un principio, con un mínimo for
bucle, y luego lo incorporó en algo más elaborado, para ayudarnos a comprender su propósito.
El bucle más simple
Esto es tan simple como puedes hacer un bucle for:
¿Te pareció bastante inútil? Sí, debería haberlo hecho. Escribí cuatro líneas de código para hacer lo que se necesita con una sola línea, echo "Hi"
.
Más elementos en la colección
«Es difícil de decir, pero se ejecutó un» bucle «. Solo se ejecutó una vez. Bien, entonces, ¿cómo hacemos que se ejecute más de una vez? Agregue más elementos (separados por espacios) a la derecha de in
palabra clave. Agreguemos cuatro 1
«más:
De acuerdo, no muy emocionante, pero el programa definitivamente parecía al menos hacer un bucle: cuatro 1
«s dieron como resultado cuatro echo
comandos en ejecución.
¿Qué sucede cuando reemplazamos esos cuatro 1
«con números diferentes? ¿Y tal vez un par de palabras?
Y … nada. Por lo tanto, el bucle no hace automáticamente nada específico para la colección de valores que le dimos. De todos modos todavía no.
Consulte la variable de ciclo
Miremos a la izquierda de la palabra clave in
, y en eso x
. ¿Cuál es el sentido de eso x
? Una x
minúscula no es el nombre de una palabra clave o comando que hemos encontrado hasta ahora (y ejecutarlo solo en el indicador arrojará un error). Entonces, ¿tal vez sea una variable? Intentemos hacer referencia a ella en la echo
declaración:
Bingo. Este es básicamente el funcionamiento fundamental de un bucle for
: – Obtener una colección de elementos / valores (Q Zebra 999 Smithsonian
) – Pasarlos a un for
construcción de bucle: utilizando la variable de bucle (x
) como marcador de posición, escriba comandos entre do
/ done
bloque.- Cuando se ejecuta el ciclo, la variable del ciclo, x
, toma el valor de cada uno de los elementos en la lista – Q
, Zebra
, 999
, Smithsonian
, – y luego se ejecuta el bloque de comandos entre do
y done
. Esta secuencia se repite una vez para cada elemento de la lista.
El bloque do
/ done
puede contener cualquier secuencia de comandos, incluso otro for
-loop:
Bucles dentro de bucles es una construcción común en programación.En su mayor parte, intentaré evitar la asignación de problemas que involucren este tipo de lógica, ya que puede ser complicado desenrollarlo durante la depuración.
Leer un archivo, línea por línea, confiablemente con read-while
Debido a que cat
imprime un archivo línea por línea, el siguiente bucle for parece sensato:
Sin embargo, la sustitución del comando hará que cat
divida las palabras por espacios. Si list-of-dirs.txt
contiene el siguiente:
La salida del ciclo for
será la siguiente:
Un ciclo de lectura mientras conserva las palabras dentro de una línea:
También podemos canalizar desde el resultado de un comando encerrándolo entre <(
y )
:
Pipes y bucles
Si viene de otros idiomas, es posible que los flujos de datos no le resulten familiares . Al menos lo son para mí, ya que la sintaxis para trabajar con ellos es mucho más directa y sencilla en Bash que en Ruby o Python.
Sin embargo, si eres nuevo en la programación en cualquier lenguaje, ¿qué podría Tampoco queda claro en qué se diferencia el trabajo con flujos de datos que con bucles.
Por ejemplo, el siguiente fragmento:
– produce la misma salida que este ciclo:
Y dependiendo de su modelo mental de las cosas, parece que en ambos ejemplos, cada palabra, por ejemplo hello
, world
, se pasa por un proceso de traducción (a través de tr
) y luego se repite.
Tubos y filtros
Sin entrar en los fundamentos del sistema Unix, en el que un tubo opera fundamentalmente diferente a un bucle aquí, permítanme sugerir una solución mental:
Los programas que se canalizan desde stdin y stdout generalmente se pueden organizar como filtros, en los que un flujo de datos entra en un programa y sale en un formato diferente:
Para tareas que son más que solo transformar datos, de filtro a filtro, piense en usar un ciclo. ¿Qué podría ser una tarea así? Dada una lista de URL, descargue cada una y envíe por correo electrónico los datos descargados, con un cuerpo y un asunto personalizados:
La fuente de entrada de datos, cada URL en urls.txt
, no se está filtrando realmente aquí. En su lugar, se está realizando una tarea de varios pasos para cada URL.
Canalización en read-while
Dicho esto, se puede implementar un bucle en sí como un filtro más entre los filtros. Tome esta variación del ciclo read-while, en el que el resultado de echo | grep
se canaliza, línea por línea, al while
bucle, que se imprime en stdout usando echo
, que se redirige al archivo llamado some.txt:
Esta no es una construcción que deba hacer a menudo, si es que lo necesita, pero con suerte refuerza el uso de tuberías en Unix.
Programación menos interactiva
La El uso frecuente de for
bucles y construcciones similares significa que «estamos pasando de los buenos viejos» días de escribir en una línea de c comandos y hacer que se ejecute justo después de presionar Enter. No importa cuántos comandos empaquetemos dentro de un bucle for
, no pasa nada hasta que presionamos la palabra clave done
.
Escribe una vez. Luego, repítalo
Con esa pérdida de interacción línea por línea con el shell, perdemos la principal ventaja del indicador interactivo: retroalimentación inmediata. Y todavía tenemos todas las desventajas: si cometemos un error tipográfico antes en el bloque de comandos entre do
y done
, tenemos que empezar por todas partes.
Así que aquí se explica cómo mitigamos eso:
Pruebe su código, un caso a la vez
Uno de los mayores errores que cometen los principiantes for
bucles si creen que un bucle for
resuelve inmediatamente su problema. Entonces, si lo que tienen que hacer es descargar 10,000 URL, pero no pueden descargar correctamente una sola URL, piensan que poner sus comandos defectuosos en un bucle for
es un paso en la dirección correcta.
Además de ser fundamentalmente malentendido de un bucle for
, el problema práctico es que ahora está ejecutando su código roto 10,000 veces, lo que significa que tiene que esperar 10,000 veces más para descubrir que su código es, por desgracia, todavía está roto.
Así que imagina que nunca has oído hablar de for
bucles. Imagina que tienes que descargar las 10,000 URL, un comando a la vez. ¿Puedes escribir el comando para hacerlo para la primera URL? ¿Qué tal el segundo? Una vez que esté razonablemente seguro de que no hay errores de sintaxis menores que lo molesten, entonces es el momento de pensar en cómo encontrar un patrón general para las otras 9.997 URL.
Escribir scripts
La línea de comandos interactiva es genial.Fue divertido empezar y lo será a lo largo de tu carrera informática. Pero cuando tienes una gran tarea por delante, que implica más de diez líneas de código, es hora de poner ese código en un script de shell. No confíe en sus dedos humanos falibles para volver a escribir el código sin problemas.
Utilice nano para trabajar en bucles y guárdelos como shell scripts. Para archivos más largos, «trabajaré en el editor de texto de mi computadora» (Sublime Text) y luego los subiré al servidor.
Ejercicio con web scraping
Solo para conectar sintaxis y funcionamiento del bucle for, aquí está el proceso de pensamiento para convertir una tarea de rutina en un bucle:
Para los números del 1 al 10, use curl para descargar la entrada de Wikipedia para cada número y guárdelo en un archivo llamado «
wiki-number-(whatever the number is).html
»
A la antigua
Con solo 10 URL, podríamos establecer un par de variables y luego copiar y pegar el comando a curl, 10 veces, haciendo cambios en cada línea:
¿Y adivina qué? Funciona. Para 10 URL, no es una mala solución y es significativamente más rápido que hacerlo a la antigua usanza (hacerlo desde su navegador web)
Reducir la repetición
Incluso sin pensar en un bucle, podemos reducir la repetición utilizando variables: la URL base, y el nombre del archivo base nunca cambian, así que asignemos esos valores a las variables. que se puede reutilizar:
Aplicando el bucle for
En este punto, hemos simplificado el patrón hasta ahora que podemos ver los pequeños cambios con cada tarea por separado. Después de aprender sobre el for
-loop, podemos aplicarlo sin pensarlo mucho (también agregamos un comando de suspensión para hacer una pausa entre las solicitudes web)
Generando un list
En la mayoría de situaciones, crear un bucle for es fácil; es la creación de la lista lo que puede ser un trabajo duro. ¿Qué pasaría si quisiéramos recopilar las páginas para los números del 1 al 100? Eso es un montón de escritura.
Pero si dejamos que nuestra pereza dicte nuestro pensamiento, podemos imaginar que contar de xay parece una tarea inherentemente computacional. Y lo es, y Unix tiene la utilidad seq
para esto:
Generando una lista de no números para iteración
Muchas tareas repetitivas ¿No son tan simples como contar de xay, por lo que el problema es cómo generar una lista no lineal de elementos? Esto es básicamente el arte de la recopilación y gestión de datos. Pero hagamos un escenario simple para nosotros mismos:
Para diez de las palabras de 10 letras (o más) que aparecen al menos una vez en un título en la página principal actual de NYTimes.com, buscar la página de Wikcionario para esa palabra
Dividimos esta tarea en dos partes:
- Obtener una lista de diez 10 + palabras de letras de los titulares de nytimes.com
- Pasar esas palabras a nuestro bucle for
Paso 1: Usar la utilidad pup (o el analizador HTML de línea de comandos de su elección):
Paso 2 (asumiendo que la variable words
se está transmitiendo):
Mira Softwa La excelente guía de re Carpentry sobre bucles for en Bash