I föregående avsnitt gick vi igenom FOR-loopen, som är användbar när du vet hur många gånger du vill upprepa en kodsekvens – till exempel när du arbetar med räknare, index eller intervall av tal. Vi har också lärt oss att en FOR-loop kräver alltid tre delar: startvärde, villkor och steg, vilket gör den flexibel men ibland lite mer formell i sin syntax.
Däremot finns det situationer där du inte är intresserad av index eller iterationens ordning, utan bara vill gå igenom varje objekt i en samling (till exempel en lista med namn, filer, tjänster eller IP-adresser). För sådana uppgifter är FOREACH-loopen betydligt enklare, tydligare och mer naturlig att använda.
I detta avsnitt fokuserar vi därför på FOREACH – hur den fungerar, när den bör användas, och hur du kan använda den för att bearbeta olika typer av data i PowerShell.
Två sätt att iterera objekt i PowerShell
I PowerShell finns två närbesläktade sätt att loopa över en samling:
1) Foreach-sats (nyckelordet) – språkkonstruktion
foreach ($item in $collection) { ... }
- Förklaring:
- foreach är en språkkonstruktion – alltså en del av själva PowerShell-syntaxen, inte en cmdlet.
- Den läser hela samlingen ($collection) in i minnet innan loopen startar. Det betyder att PowerShell först hämtar alla objekt, till exempel en lista eller array, och sedan arbetar på dem i minnet.
- Därefter går PowerShell igenom ett objekt i taget ur samlingen (hämtas från minnet och läggs till variabeln $item).
- Vid varje varv i loopen tilldelas variabeln $item det aktuella objektet.
- Det gör foreach snabb och effektiv när du redan har en färdig samling i en variabel — till exempel efter att du har kört ett kommando och sparat resultatet.
2) ForEach-Object (cmdlet i pipen) – cmdlet
$collection | ForEach-Object { ... } # alias: %
- Förklaring
- ForEach-Object är en cmdlet – alltså ett PowerShell-kommando som körs i pipeline-flödet.
- Den bearbetar objekt ett i taget medan de passerar genom pipelinen. Inget behöver läsas in i minnet på förhand.
- Det gör att den är bättre vid stora datamängder eller när du kedjar flera cmdlets.
- Varje objekt som kommer från föregående kommando blir tillgängligt som $_ , den automatiska variabeln som representerar det aktuella objektet i pipen.
Dessa två sätt gör samma sak logiskt (”för varje objekt, gör X”), men kontexten (variabel vs. pipeline) avgör vilket som känns mest naturligt.
Syntax (Foreach-sats)
foreach ($item in $collection) { # åtgärder för varje $item }
- $item är loop-variabeln (ny referens för varje objekt i samlingen).
- $collection är samlingen (array, lista, resultatet från ett kommando m.m.).
Exempel på användning av FOREACH
- Hälsa på varje namn i en array
- Skriva ut talen 1 till 10
- Lista filer och mappar som finns i C:\
- Multiplikationstabeller 1–5 (varje 1–10)
- Visa de fem första tjänsterna (services)
- Är talen 1–25 delbara med 10?
- Multiplicera negativa tal (−5 till −1) med 2
1) Hälsa på varje namn i en array
$names = @("Alice", "Bob", "Charlie") foreach ($name in $names) { Write-Host "Hello, $name!" }
- Utdata
- Hello, Alice!
- Hello, Bob!
- Hello, Charlie!
- Förklaring
- @("Alice", "Bob", "Charlie") skapar en array med tre strängar.
- $name tar värdet av varje element i tur och ordning.
- Write-Host skriver direkt till konsolen. (Tips: Write-Host är bäst för ren skärmtext.)
Alternativ (pipeline)
$names = @("Alice", "Bob", "Charlie") $names | ForEach-Object { "Hello, $_!" }
- @("Alice", "Bob", "Charlie") skapar en array med tre strängar.
- | skickar arrayen som pipeline-input till cmdleten ForEach-Object.
- Inuti blocket { "Hello, $_!"} används den automatiska variabeln $_ , som representerar det aktuella objektet i pipen, i detta fall varje namn.
2) Skriva ut talen 1 till 10
$myArray = 1,2,3,4,5,6,7,8,9,10 foreach ($number in $myArray) { echo $number }
- Förklaring
- echo är alias för Write-Output.
- $myArray = 1,2,3,4,5,6,7,8,9,10 skapar en array (en lista) som innehåller heltalen 1 till 10.
- foreach ($number in $myArray) börjar själva loopen.
Den säger i princip: “För varje element i samlingen $myArray, tilldela värdet till den tillfälliga variabeln $number.” - Det betyder att PowerShell:
- Tar första värdet i arrayen (1), tilldelar det till $number, och kör kodblocket { echo $number }
- Går vidare till nästa värde (2), tilldelar det till $number, och kör kodblocket igen
- Och så vidare, tills alla värden i $myArray har bearbetats.
- Vid varje iteration innehåller $number ett nytt värde från arrayen.
Enklare variant med range-operatorn ..:
foreach ($number in 1..10) { Write-Output $number }
- Förklaring
- 1..10 genererar en sekvens av heltal från 1 till 10.
- Varje iteration skickar talet till utdata (kan också pipas vidare).
3) Lista filer och mappar som finns i C:\
foreach ($entry in (Get-ChildItem -Path C:\)) { Write-Output $entry }
- Förklaring
- Get-ChildItem -Path C:\
- Hämtar alla objekt (filer och mappar) i katalogen C:\.
- Varje objekt som returneras är ett .NET-objekt av typen System.IO.FileInfo (för filer) eller System.IO.DirectoryInfo (för mappar).
- Resultatet är alltså en samling objekt, inte bara text.
- foreach ($entry in (...))
- Loopen tar ett objekt i taget ur resultatet från Get-ChildItem.
- Vid varje varv tilldelas det aktuella objektet till variabeln $entry. Exempelvis:
- Första iterationen tilldelas $entry = C:\Program Files
- Nästa tilldelas $entry = C:\Windows
- Sedan tilldelas $entry = C:\pagefile.sys
- och så vidare.
- Write-Output $entry
- Skriver ut värdet av $entry till pipeline eller till skärmen, i exemplet till skärmen.
- Eftersom $entry är ett objekt visas dess namn i standardformat.
- (Skillnaden mot Write-Host är att Write-Output kan skickas vidare till andra kommandon i en pipeline, medan Write-Host bara visar text.)
- Get-ChildItem -Path C:\
eller så här:
Get-ChildItem -Path C:\ | ForEach-Object { $_ }
- Förklaring
- Get-ChildItem -Path C:\ hämtar alla objekt i katalogen C:\.
- Dessa objekt är .NET-objekt av typerna:
- System.IO.FileInfo (för filer)
- System.IO.DirectoryInfo (för mappar)
- | (pipeline) skickar varje objekt som hittas till nästa kommando i kedjan, ett i taget.
- ForEach-Object { $_ } kör kodblocket { $_ } en gång för varje objekt som kommer genom pipen.
- Den automatiska variabeln $_ representerar det aktuella objektet. I det här fallet visar den helt enkelt objektet som det är, vilket gör att PowerShell skriver ut fil- och mappnamn.
Filtrera gärna:
Get-ChildItem -Path C:\ -Directory | ForEach-Object { $_.FullName }
- Visar bara mapparnas fulla sökvägar.
4) Multiplikationstabeller 1–5 (varje 1–10)
foreach ($i in 1..5) { foreach ($j in 1..10) { $result = $j * $i # Snyggt jämn kolumnlayout med -f -formatsträng: "{0,2} x {1,2} = {2,3}" -f $j, $i, $result } "" # tom rad mellan tabellerna }
Detta exempel visar hur nästade foreach-loopar fungerar — det vill säga en loop inuti en annan loop.
- Den yttre loopen (foreach ($i in 1..5)) bestämmer vilken tabell som ska skrivas ut (tabell 1, tabell 2, … tabell 5).
- Den inre loopen (foreach ($j in 1..10)) räknar från 1 till 10 och multiplicerar varje tal med värdet i den yttre loopen. På så sätt får du 10 rader för varje tabell.
- Uttrycket "{0,2} x {1,2} = {2,3}" -f $j, $i, $result använder format-operatorn -f för att skapa en snyggt formaterad utskrift där talen högerjusteras i kolumner.
- {0,2} betyder: skriv första värdet ($j) med bredden 2 tecken.
- {1,2} betyder: skriv andra värdet ($i) med bredden 2.
- {2,3} betyder: skriv tredje värdet ($result) med bredden 3.
- Detta gör tabellen lättare att läsa, särskilt när talen blir tvåsiffriga.
- Raden med en tom sträng ("") används för att lägga in en mellanrad mellan varje tabell, så att resultatet blir tydligt uppdelat.
- Sammanfattning
- Yttre loop (foreach ($i in 1..5)) väljer tabell (1–5)
- Inre loop (foreach ($j in 1..10)) räknar 1–10 och beräknar produkterna
- -f gör utskriften prydlig och justerad
- Tom rad skapar luft mellan tabellerna
- Resultatet blir fem separata, lättlästa multiplikationstabeller.
Tips: Om du vill ha rubriker per tabell:
foreach ($i in 1..5) { "Tabell $i" 1..10 | ForEach-Object { "{0,2} x {1,2} = {2,3}" -f $_, $i, ($_ * $i) } "" }
5) Visa de fem första tjänsterna (services)
foreach ($service in (Get-Service | Select-Object -First 5)) { Write-Host "Service name: $($service.Name) Status: $($service.Status)" }
- Get-Service | Select-Object -First 5
- Get-Service hämtar en lista över alla tjänster (services) på datorn.
- Varje tjänst representeras som ett objekt med flera egenskaper, t.ex. Name, DisplayName, Status, ServiceType, osv.
- Select-Object -First 5 begränsar resultatet till de första fem tjänsterna.
- foreach ($service in (...))
- foreach är en språkkonstruktion (loop) som går igenom varje objekt i samlingen, ett i taget.
- Variabeln $service får i varje varv ett av service-objekten som hämtats i parentesen.
- Write-Host "Service name: $($service.Name) Status: $($service.Status)"
- Write-Host skriver text direkt till skärmen.
- Inuti textsträngen används uttrycks-interpolering ($()):
- $($service.Name) hämtar namnet på tjänsten.
- $($service.Status) hämtar statusen (t.ex. Running, Stopped).
- $() används för att PowerShell ska utvärdera uttrycket inuti parentesen innan texten skrivs ut.
Exempel på utdata (varierar per dator)
Service name: AdobeARMservice Status: Running Service name: AppIDSvc Status: Stopped ...
Vid filtrering
Get-Service | Where-Object Status -eq 'Running' | Select-Object -First 5 | ForEach-Object { "Running: $($_.Name)" }
- Get-Service hämtar alla tjänster (services) på systemet.
Varje tjänst är ett objekt med flera egenskaper, bland annat Name, DisplayName, Status. - Where-Object Status -eq 'Running' filtrerar tjänsterna
- Where-Object används för att välja ut de objekt som uppfyller ett villkor.
- Status -eq 'Running' betyder “ta bara de tjänster där egenskapen Status är lika med Running”.
- Select-Object -First 5 väljer de fem första objekten som finns kvar efter filtreringen.
- ForEach-Object { "Running: $($_.Name)" }
- Här används cmdleten ForEach-Object för att bearbeta varje objekt som kommer genom pipen.
- Varje tjänst representeras i loopen som $_ (den automatiska variabeln för “aktuellt objekt”).
- Inuti blocket { ... } skapas en textsträng:
- "Running: $($_.Name)" där $($_.Name) hämtar namnet på den aktuella tjänsten.
- PowerShell skriver ut varje textsträng i tur och ordning.
6) Är talen 1–25 delbara med 10?
foreach ($n in 1..25) { if ($n % 10 -eq 0) { "$n is like totally divisible by ten" } }
- Uttrycket 1..25 skapar en sekvens av heltal från 1 till 25.
- Det är alltså samma som att skriva: @(1, 2, 3, 4, ..., 25)
- Denna lista används som samlingen som loopen ska iterera över.
- foreach ($n in 1..25) startar foreach-loopen.
- Variabeln $n kommer att få ett nytt värde vid varje iteration, från 1 till 25.
- Alltså: första varvet $n = 1, andra varvet $n = 2, … och sista $n = 25.
- if ($n % 10 -eq 0) villkoret kontrollerar om $n är jämnt delbart med 10.
- Operatorn % betyder modulo – den returnerar resten vid division.
- Exempel:
- 10 % 10 = 0 (inga rester, alltså delbart)
- 15 % 10 = 5 (resten 5, alltså inte delbart)
- Så uttrycket $n % 10 -eq 0 betyder “Om talet $n går jämnt upp i 10, gör detta...”
- "$n is like totally divisible by ten"
- Operatorn % betyder modulo – den returnerar resten vid division.
- Om villkoret i if-satsen är sant, skriver PowerShell ut texten.
- Eftersom strängen står ensam i blocket, returneras och visas den automatiskt i konsolen.
- Utdata
10 is like totally divisible by ten 20 is like totally divisible by ten
7) Multiplicera negativa tal (−5 till −1) med 2
$negativeNumbers = -5..-1 foreach ($n in $negativeNumbers) { $n * 2 }
- Förklaring
- $negativeNumbers = -5..-1 skapar en sekvens av heltal från –5 till –1 och tilldelas dessa värde till $negativeNumbers.
- PowerShells intervall-operator .. fungerar även med negativa tal.
- Alltså: $negativeNumbers = @(-5, -4, -3, -2, -1)
- foreach ($n in $negativeNumbers)
- foreach-loopen går igenom varje element i listan, ett i taget:
- Första varvet: $n = -5
- Andra varvet: $n = -4
- … och så vidare tills $n = -1.
- foreach-loopen går igenom varje element i listan, ett i taget:
- $n * 2 multiplicerar det aktuella talet med 2.
- Eftersom raden inte innehåller Write-Host eller Write-Output, returneras resultatet automatiskt i konsolen.
- Beräkningarna blir:
- -5 * 2 = -10
- -4 * 2 = -8
- -3 * 2 = -6
- -2 * 2 = -4
- -1 * 2 = -2
- Resultat i konsolen
-10 -8 -6 -4 -2
Vanliga tips och fallgropar
- Välj rätt form
- Har du redan en samling i en variabel → foreach ($x in $collection) { ... }.
- Bygger du ett pipeline-flöde → ... | ForEach-Object { ... }.
- Prestanda och minne
- ForEach-Object strömmar objekt (bra för stora mängder).
- Foreach-satsen materialiserar samlingen först (snabb i ren loop, men kräver att allt får plats).
- Skriv ut rätt
- Write-Output för data som kanske ska vidare i pipeline.
- Write-Host för ren skärmtext (färg, rubriker).
- Undvik att mutera samlingen du itererar
- Lägg hellre till/ta bort objekt i en separat lista under loopen.
- Formattering
- Använd -f för kolumnsnyggt resultat när sifferkolumner ska läsas av människor.
- $_ vs. namngiven variabel
- I pipeline använder du oftast $_ . I foreach-satsen är en namngiven loopvariabel (t.ex. $item) oftast tydligare i undervisningsmaterial.
4) Multiplikationstabeller 1–5 (varje 1–10)
foreach ($i in 1..5) { foreach ($j in 1..10) { $result = $j * $i # Snyggt jämn kolumnlayout med -f -formatsträng: "{0,2} x {1,2} = {2,3}" -f $j, $i, $result } "" # tom rad mellan tabellerna }
Detta exempel visar hur nästade foreach-loopar fungerar — det vill säga en loop inuti en annan loop.
- Den yttre loopen (foreach ($i in 1..5)) bestämmer vilken tabell som ska skrivas ut (tabell 1, tabell 2, … tabell 5).
- Den inre loopen (foreach ($j in 1..10)) räknar från 1 till 10 och multiplicerar varje tal med värdet i den yttre loopen. På så sätt får du 10 rader för varje tabell.
- Uttrycket "{0,2} x {1,2} = {2,3}" -f $j, $i, $result använder format-operatorn -f för att skapa en snyggt formaterad utskrift där talen högerjusteras i kolumner.
- {0,2} betyder: skriv första värdet ($j) med bredden 2 tecken.
- {1,2} betyder: skriv andra värdet ($i) med bredden 2.
- {2,3} betyder: skriv tredje värdet ($result) med bredden 3.
- Detta gör tabellen lättare att läsa, särskilt när talen blir tvåsiffriga.
- Raden med en tom sträng ("") används för att lägga in en mellanrad mellan varje tabell, så att resultatet blir tydligt uppdelat.
- Sammanfattning
- Yttre loop (foreach ($i in 1..5)) väljer tabell (1–5)
- Inre loop (foreach ($j in 1..10)) räknar 1–10 och beräknar produkterna
- -f gör utskriften prydlig och justerad
- Tom rad skapar luft mellan tabellerna
- Resultatet blir fem separata, lättlästa multiplikationstabeller.
Tips: Om du vill ha rubriker per tabell:
foreach ($i in 1..5) { "Tabell $i" 1..10 | ForEach-Object { "{0,2} x {1,2} = {2,3}" -f $_, $i, ($_ * $i) } "" }
5) Visa de fem första tjänsterna (services)
foreach ($service in (Get-Service | Select-Object -First 5)) { Write-Host "Service name: $($service.Name) Status: $($service.Status)" }
- Get-Service | Select-Object -First 5
- Get-Service hämtar en lista över alla tjänster (services) på datorn.
- Varje tjänst representeras som ett objekt med flera egenskaper, t.ex. Name, DisplayName, Status, ServiceType, osv.
- Select-Object -First 5 begränsar resultatet till de första fem tjänsterna.
- foreach ($service in (...))
- foreach är en språkkonstruktion (loop) som går igenom varje objekt i samlingen, ett i taget.
- Variabeln $service får i varje varv ett av service-objekten som hämtats i parentesen.
- Write-Host "Service name: $($service.Name) Status: $($service.Status)"
- Write-Host skriver text direkt till skärmen.
- Inuti textsträngen används uttrycks-interpolering ($()):
- $($service.Name) hämtar namnet på tjänsten.
- $($service.Status) hämtar statusen (t.ex. Running, Stopped).
- $() används för att PowerShell ska utvärdera uttrycket inuti parentesen innan texten skrivs ut.
Exempel på utdata (varierar per dator)
Service name: AdobeARMservice Status: Running Service name: AppIDSvc Status: Stopped ...
Vid filtrering
Get-Service | Where-Object Status -eq 'Running' | Select-Object -First 5 |
ForEach-Object { "Running: $($_.Name)" }
- Get-Service hämtar alla tjänster (services) på systemet.
Varje tjänst är ett objekt med flera egenskaper, bland annat Name, DisplayName, Status. - Where-Object Status -eq 'Running' filtrerar tjänsterna
- Where-Object används för att välja ut de objekt som uppfyller ett villkor.
- Status -eq 'Running' betyder “ta bara de tjänster där egenskapen Status är lika med Running”.
- Select-Object -First 5 väljer de fem första objekten som finns kvar efter filtreringen.
- ForEach-Object { "Running: $($_.Name)" }
- Här används cmdleten ForEach-Object för att bearbeta varje objekt som kommer genom pipen.
- Varje tjänst representeras i loopen som $_ (den automatiska variabeln för “aktuellt objekt”).
- Inuti blocket { ... } skapas en textsträng:
- "Running: $($_.Name)" där $($_.Name) hämtar namnet på den aktuella tjänsten.
- PowerShell skriver ut varje textsträng i tur och ordning.
6) Är talen 1–25 delbara med 10?
foreach ($n in 1..25) { if ($n % 10 -eq 0) { "$n is like totally divisible by ten" } }
- Uttrycket 1..25 skapar en sekvens av heltal från 1 till 25.
- Det är alltså samma som att skriva: @(1, 2, 3, 4, ..., 25)
- Denna lista används som samlingen som loopen ska iterera över.
- foreach ($n in 1..25) startar foreach-loopen.
- Variabeln $n kommer att få ett nytt värde vid varje iteration, från 1 till 25.
- Alltså: första varvet $n = 1, andra varvet $n = 2, … och sista $n = 25.
- if ($n % 10 -eq 0) villkoret kontrollerar om $n är jämnt delbart med 10.
- Operatorn % betyder modulo – den returnerar resten vid division.
- Exempel:
- 10 % 10 = 0 (inga rester, alltså delbart)
- 15 % 10 = 5 (resten 5, alltså inte delbart)
- Så uttrycket $n % 10 -eq 0 betyder “Om talet $n går jämnt upp i 10, gör detta...”
- "$n is like totally divisible by ten"
- Operatorn % betyder modulo – den returnerar resten vid division.
- Om villkoret i if-satsen är sant, skriver PowerShell ut texten.
- Eftersom strängen står ensam i blocket, returneras och visas den automatiskt i konsolen.
- Utdata
10 is like totally divisible by ten 20 is like totally divisible by ten
7) Multiplicera negativa tal (−5 till −1) med 2
$negativeNumbers = -5..-1
foreach ($n in $negativeNumbers) { $n * 2 }
- Förklaring
- $negativeNumbers = -5..-1 skapar en sekvens av heltal från –5 till –1 och tilldelas dessa värde till $negativeNumbers.
- PowerShells intervall-operator .. fungerar även med negativa tal.
- Alltså: $negativeNumbers = @(-5, -4, -3, -2, -1)
- foreach ($n in $negativeNumbers)
- foreach-loopen går igenom varje element i listan, ett i taget:
- Första varvet: $n = -5
- Andra varvet: $n = -4
- … och så vidare tills $n = -1.
- foreach-loopen går igenom varje element i listan, ett i taget:
- $n * 2 multiplicerar det aktuella talet med 2.
- Eftersom raden inte innehåller Write-Host eller Write-Output, returneras resultatet automatiskt i konsolen.
- Beräkningarna blir:
- -5 * 2 = -10
- -4 * 2 = -8
- -3 * 2 = -6
- -2 * 2 = -4
- -1 * 2 = -2
- Resultat i konsolen
-10 -8 -6 -4 -2