Laços for e foreach
Esta aula aborda os laços for e foreach no PowerShell, incluindo a estrutura do for clássico, o foreach para coleções e a diferença entre o comando foreach e o cmdlet ForEach-Object. Exemplos práticos demonstram o uso de cada estrutura.
Nesta aula, vamos explorar dois dos laços mais importantes no PowerShell: for e foreach. O laço for é ideal quando você precisa controlar explicitamente o número de iterações, enquanto o foreach simplifica a iteração sobre coleções de objetos. Entender essas estruturas é fundamental para escrever scripts eficientes e legíveis.
for
O laço for no PowerShell segue a mesma sintaxe de outras linguagens: for (inicialização; condição; incremento) { bloco de comandos }. Ele é útil quando você precisa iterar um número conhecido de vezes, especialmente quando precisa de um contador.
A inicialização é executada uma vez antes do laço. A condição é testada antes de cada iteração; se for verdadeira, o bloco é executado. Após cada iteração, o incremento é executado. O laço termina quando a condição se torna falsa.
Exemplo: exibir números de 1 a 5.
for ($i = 1; $i -le 5; $i++) {
Write-Host "Número: $i"
}
Saída:
Número: 1
Número: 2
Número: 3
Número: 4
Número: 5
foreach (statement)
O comando foreach é usado para iterar sobre uma coleção de itens, como uma lista, array ou saída de cmdlet. Sua sintaxe é: foreach ($item in $coleção) { bloco de comandos }. Ele é mais legível que o for quando você não precisa de um contador.
Exemplo: exibir cada elemento de um array.
$frutas = @('Maçã', 'Banana', 'Laranja')
foreach ($fruta in $frutas) {
Write-Host "Fruta: $fruta"
}
Saída:
Fruta: Maçã
Fruta: Banana
Fruta: Laranja
Diferença para ForEach-Object
ForEach-Object é um cmdlet que processa objetos do pipeline, enquanto foreach é uma instrução de linguagem. A principal diferença é que foreach carrega toda a coleção na memória antes de iterar, enquanto ForEach-Object processa cada objeto conforme ele passa pelo pipeline (streaming), economizando memória para grandes conjuntos de dados.
Exemplo com ForEach-Object:
1..5 | ForEach-Object { Write-Host "Número: $_" }
Saída:
Número: 1
Número: 2
Número: 3
Número: 4
Número: 5
Já o foreach faria:
foreach ($n in 1..5) { Write-Host "Número: $n" }
Para pipelines muito grandes, prefira ForEach-Object para evitar consumo excessivo de memória.
Exemplos
Exemplo 1: Calcular a soma dos números de 1 a 100 com for.
$soma = 0
for ($i = 1; $i -le 100; $i++) {
$soma += $i
}
Write-Host "Soma: $soma"
Exemplo 2: Listar todos os processos em execução com foreach.
$processos = Get-Process
foreach ($proc in $processos) {
Write-Host "Processo: $($proc.Name) - PID: $($proc.Id)"
}
Exemplo 3: Usar ForEach-Object para filtrar e exibir apenas processos com mais de 10 MB de memória.
Get-Process | Where-Object { $_.WorkingSet -gt 10MB } | ForEach-Object {
Write-Host "$($_.Name) está usando $($_.WorkingSet / 1MB) MB"
}
Boas Práticas
- Use
forquando precisar de um contador ou iteração com índice. - Use
foreachpara iterar coleções completas de forma legível. - Use
ForEach-Objectem pipelines para processamento streaming. - Evite modificar a coleção dentro de um
foreach; isso pode causar erros. - Prefira
ForEach-Objectcom-Parallel(PowerShell 7+) para paralelismo.
Referências
- about_For - PowerShell Documentation
- about_Foreach - PowerShell Documentation
- ForEach-Object Cmdlet
- about_Loops - PowerShell Documentation
- about_Pipelines - PowerShell Documentation
Exercícios
-
Escreva um script que exiba os números pares de 0 a 20 usando o laço
for.✓ Resposta:for ($i = 0; $i -le 20; $i += 2) { Write-Host $i } -
Dado o array
$nomes = @('Ana', 'Beto', 'Carla'), useforeachpara exibir cada nome em maiúsculas.✓ Resposta:$nomes = @('Ana', 'Beto', 'Carla') foreach ($nome in $nomes) { Write-Host $nome.ToUpper() } -
Use
ForEach-Objectpara exibir o nome de cada serviço que está em execução (status Running).✓ Resposta:Get-Service | Where-Object { $_.Status -eq 'Running' } | ForEach-Object { $_.Name } -
Escreva um laço
forque calcule o fatorial de 5 (5!).✓ Resposta:$fatorial = 1 for ($i = 1; $i -le 5; $i++) { $fatorial *= $i } Write-Host "5! = $fatorial" -
Converta o seguinte uso de
ForEach-Objectpara um laçoforeach:1..10 | ForEach-Object { $_ * $_ }✓ Resposta:foreach ($n in 1..10) { $n * $n }