Saltar al contenido

El bucle de anteojos de PowerShell: Qué es y cómo se usa

Si estás familiarizado con las prácticas comunes de codificación, probablemente también estés familiarizado con un bucle de frente. Un bucle foreach es una construcción de lenguaje simple que le permite iterar a través de un conjunto de elementos en una colección o matriz. Todos los lenguajes de programación tienen bucles foreach, y todos ellos tienden a comportarse de la misma manera. PowerShell, por otro lado – con su tubería, cmdlets incorporados, y el uso de alias – a veces hace tropezar a los novatos. Piensan que PowerShell sólo tiene un único lazo frontal. El novato estaría equivocado.

Para complicar las cosas, PowerShell tiene dos construcciones de frente distintas; la declaración de frente y el cmdlet de frente al objeto. Aunque son similares, cada una se comporta de manera muy diferente. En la superficie, podrías preguntarte cómo alguien podría mezclarlas. Uno es de siete caracteres y el otro de 14, pero mira esto:

El bucle de anteojos de PowerShell: Qué es y cómo se usa
El bucle de anteojos de PowerShell: Qué es y cómo se usa

Como un alias, cada uno es igual a cada objeto. Ahora, ¿ves de dónde viene la confusión? En realidad, foreach es un alias para el cmdlet de Cada Objeto, y foreach (no el alias) es una declaración. Cada uno tiene su propósito.

El cmdlet de ForEach-Object

El cmdlet de ForEach-Object (alias de foreach) se utiliza en la tubería. Se utiliza para iterar a través de una colección de artículos, mientras se respeta la tubería de PowerShell, que recibe la entrada, la procesa y la pasa por la tubería a medida que los objetos son procesados. Consume una memoria mínima porque está consumiendo memoria para cada objeto y liberándola a medida que toca cada objeto. Piensa en cada objeto como una cinta transportadora. Recoge cada «paquete» a medida que pasa por la cinta transportadora, lo inspecciona, lo vuelve a colocar en su sitio y repite el proceso a medida que se envían más «paquetes» por la línea.

Aquí hay un ejemplo de la conducta de un Objeto de la Tierra:

Notarán que el Objeto de Medida recibió 10.001 objetos. Esto se debe a que ForEach-Object procesó cada objeto y lo envió inmediatamente.

Intentemos que sea confuso:

Esta es exactamente la misma línea que vimos antes. Pero en lugar de usar la sintaxis completa de cada objeto, elegí usar el alias de foreach y pasar el parámetro -InputObject a través de la tubería a ForEach-Object.

Ahora veamos cuánto tiempo tomó eso:

163 milisegundos. No está mal para iterar a través de 10.000 artículos.

La declaración de foreach

La declaración de foreach (como ForEach-Object) itera a través de una colección de artículos, pero asigna toda la memoria que necesita por adelantado e ignora por completo la tubería. Para mí, la declaración de foreach es comparable a las construcciones de foreach en otros lenguajes de programación. Una forma fácil de diferenciar la declaración de foreach del cmdlet de ForEach-Object (incluso si está siendo enmascarado como un alias) es que el alias de ForEach-Object nunca puede ser especificado al comienzo de una línea.

Puedes ver que este guión bombardea. Pero si miran nuestro primer ejemplo de ForEach-Object, funcionó muy bien. Esto es porque no estamos usando el alias de ForEach-Object aquí. Estamos usando la declaración de ForEach-Object.

Intentemos la declaración de foreach usando el mismo código que intentamos previamente con ForEach-Object:

Recibimos el mensaje de error «No se permite un elemento de tubería vacío». Esto se debe a que después del personaje de la tubería, ¡no hay ninguna tubería! ¡Desapareció! A la declaración de Foreach no le podría importar menos la tubería de PowerShell – procede a acaparar todos los objetos y rompe completamente la tubería.

Cronometremos la declaración de cada uno de los objetos de la misma manera que lo hicimos con cada uno de los objetos:

Recordarán que tomó 163 milisegundos para iterar a través de 10.000 artículos con ForEach-Object. La declaración de cada uno de ellos tomó 17 milisegundos. ¡Eso es casi 10 veces más rápido! Aunque la declaración de la frente fue definitivamente más rápida, consumió más memoria mientras procesaba el resultado.

Ahora que ve las diferencias, ¿qué construcción es más probable que use? Como con cualquier fenómeno tecnológico, la mejor elección depende de tu situación, el tipo de problema que intentas resolver y el objetivo del guión. Siempre utilizo la frase preliminar. Puedes ver que es mucho más rápido y que itera a través de los elementos de la misma manera. La única desventaja es que consume más memoria. Pero con los sistemas de hoy en día, eso no suele ser un problema.

Si no necesitas guardar la memoria, y no tienes una razón de nicho para usar el oleoducto, te recomiendo usar la declaración de foreach. Sin embargo, si estás procesando grandes conjuntos de datos que pueden consumir gigabytes de memoria, te verás obligado a usar la declaración de ForEach-Object. De lo contrario, sólo tienes que ceñirte a la declaración de foreach.