Language lab · Beginner → Ops
💠 PowerShell
Concept → trace → write code → run tests → explain why → improve → mini-project. Start in the browser if you like; set up your own computer when you are ready.
📖 Topics with real code (15)
Every verified output below was produced by running the code with PowerShell 7.4.2 on 5 Nov 2026. Open a topic to edit the code and run it on your own computer with the real compiler, through the free GayaGnan agent.
🌱 Beginner (5)
Variables and types
Variables start with $. PowerShell works with .NET objects, so values keep real types: [int], [double], [bool], [string]. GetType() shows the type; a cast like [int]"88" converts.
$age = 15 $height = 1.62 $isStudent = $true $name = "Asha" "$name $age $height $isStudent" "$($age.GetType().Name) $($height.GetType().Name) $($isStudent.GetType().Name) $($name.GetType().Name)" [int]"88" + 2 "7 / 2 = $(7 / 2), truncated $([math]::Truncate(7 / 2)), [int]9.6 rounds to $([int]9.6)" [int]::MaxValue
✅ Verified output
Asha 15 1.62 True Int32 Double Boolean String 90 7 / 2 = 3.5, truncated 3, [int]9.6 rounds to 10 2147483647
Operators and boolean logic
Comparison operators are words: -eq -ne -gt -lt -ge -le, plus -like and -match for text. Logical: -and -or -not. Comparisons ignore case unless you use -ceq.
$a = 17; $b = 5
"$($a + $b) $($a - $b) $($a * $b) $($a / $b) $($a % $b) $([math]::Pow($a, 2))"
"17 -gt 5: $($a -gt $b) 'ABC' -eq 'abc': $('ABC' -eq 'abc') -ceq: $('ABC' -ceq 'abc')"
$hasTicket = $true; $isVip = $false
"enter: $($hasTicket -and -not $isVip) either: $($hasTicket -or $isVip)"
"report.pdf" -like "*.pdf"
"roll R42" -match "R(\d+)"; "matched number: $($Matches[1])"
✅ Verified output
22 12 85 3.4 2 289 17 -gt 5: True 'ABC' -eq 'abc': True -ceq: False enter: True either: True True True matched number: 42
Conditionals: if and switch
if/elseif/else picks a branch. switch can match exact values, wildcards (-Wildcard) or regex (-Regex), and can loop over a list.
$marks = 78
if ($marks -ge 90) { $grade = "A+" }
elseif ($marks -ge 75) { $grade = "A" }
elseif ($marks -ge 35) { $grade = "Pass" }
else { $grade = "Fail" }
"Grade: $grade"
switch -Wildcard ("report.pdf", "photo.jpg", "notes.txt") {
"*.pdf" { "$_ -> document" }
"*.jpg" { "$_ -> image" }
default { "$_ -> other" }
}
✅ Verified output
Grade: A report.pdf -> document photo.jpg -> image notes.txt -> other
Loops: for, foreach, while and the pipeline
foreach walks a collection; ForEach-Object processes pipeline items one by one ($_ is the current item). 1..5 makes a range.
for ($i = 1; $i -le 5; $i++) {
if ($i -eq 3) { continue }
"for $i"
}
$n = 10
while ($n -gt 0) {
if ($n -lt 4) { break }
"while $n"
$n -= 3
}
foreach ($c in "red", "green") { "foreach $c" }
1..3 | ForEach-Object { ($_ * 10).ToString().PadLeft(4) }
✅ Verified output
for 1 for 2 for 4 for 5 while 10 while 7 while 4 foreach red foreach green 10 20 30
Functions and parameters
A function has a param() block with types, defaults and [Parameter(Mandatory)]. Anything written to the output is the return value.
function Get-Area {
param([int]$Length, [int]$Width = 1)
$Length * $Width
}
function Get-Average {
param([Parameter(Mandatory)][int[]]$Numbers)
($Numbers | Measure-Object -Average).Average
}
"area $(Get-Area -Length 5 -Width 3) and $(Get-Area 7)"
"average $(Get-Average -Numbers 4, 9, 2, 7)"
function Test-Even([int]$n) { $n % 2 -eq 0 }
"10 even? $(Test-Even 10) 7 even? $(Test-Even 7)"
✅ Verified output
area 15 and 7 average 5.5 10 even? True 7 even? False
🌿 Intermediate (6)
Arrays and the pipeline
@() makes an array; += adds (by copying). Where-Object filters, Sort-Object sorts, Measure-Object counts and sums.
$marks = @(72, 95, 64, 88)
$marks += 91
$sorted = $marks | Sort-Object
"sorted: $sorted first: $($sorted[0]) last: $($sorted[-1]) count: $($marks.Count)"
$high = $marks | Where-Object { $_ -ge 80 }
"80 and above: $high"
$stats = $marks | Measure-Object -Sum -Average -Maximum
"sum $($stats.Sum) avg $($stats.Average) max $($stats.Maximum)"
"odd squares: $((1..5 | Where-Object { $_ % 2 } | ForEach-Object { $_ * $_ }) -join ', ')"
✅ Verified output
sorted: 64 72 88 91 95 first: 64 last: 95 count: 5 80 and above: 95 88 91 sum 410 avg 82 max 95 odd squares: 1, 9, 25
Strings and formatting
Double quotes expand variables and $( ) expressions. -f formats like String.Format. .NET string methods (Trim, Replace, Split, ToUpper) all work.
$t = " GayaGnan learning ".Trim()
"$($t.ToUpper()) | $($t.Replace('learning', 'labs')) | $($t.Length)"
$words = $t.Split(" ")
$words -join "-"
"Total: {0:N2} for {1} items" -f (49.5 * 3), 3
'single quotes do not expand $t'
$here = @"
Name: $t
Line two
"@
$here
✅ Verified output
GAYAGNAN LEARNING | GayaGnan labs | 17 GayaGnan-learning Total: 148.50 for 3 items single quotes do not expand $t Name: GayaGnan learning Line two
Hashtables and custom objects
@{} makes a hashtable (key-value). [ordered] keeps insertion order. [PSCustomObject] turns a hashtable into an object with properties, which tables and CSV understand.
$stock = [ordered]@{ pen = 40; book = 12 }
$stock["eraser"] = 25
$stock.pen -= 5
$stock.GetEnumerator() | ForEach-Object { "$($_.Key) $($_.Value)" }
"has ruler? $($stock.Contains('ruler'))"
$students = @(
[PSCustomObject]@{ Name = "Asha"; Marks = 88 }
[PSCustomObject]@{ Name = "Ravi"; Marks = 95 }
)
$students | Sort-Object Marks -Descending | Format-Table -AutoSize | Out-String -Width 60
"the cat and the hat" -split " " | Group-Object | Sort-Object Name | ForEach-Object { "$($_.Name)=$($_.Count)" }
✅ Verified output
pen 35 book 12 eraser 25 has ruler? False Name Marks ---- ----- Ravi 95 Asha 88 and=1 cat=1 hat=1 the=2
Classes in PowerShell
PowerShell 5+ supports classes with typed properties, constructors, methods and inheritance.
class BankAccount {
[string]$Owner
hidden [decimal]$Balance
BankAccount([string]$owner, [decimal]$balance) { $this.Owner = $owner; $this.Balance = $balance }
[void] Deposit([decimal]$amount) {
if ($amount -le 0) { throw "amount must be positive" }
$this.Balance += $amount
}
[decimal] GetBalance() { return $this.Balance }
}
class Savings : BankAccount {
Savings([string]$o) : base($o, 0) {}
[void] AddInterest() { $this.Deposit($this.GetBalance() * 0.05) }
}
$acc = [BankAccount]::new("Asha", 500)
$acc.Deposit(250)
"$($acc.Owner) $($acc.GetBalance())"
$s = [Savings]::new("Ravi"); $s.Deposit(1000); $s.AddInterest()
"$($s.Owner) $($s.GetBalance())"
✅ Verified output
Asha 750 Ravi 1050.00
Errors: try/catch, -ErrorAction and $Error
Terminating errors go to catch. Many cmdlets write non-terminating errors; -ErrorAction Stop turns them into catchable ones.
try {
Get-Item (Join-Path ([System.IO.Path]::GetTempPath()) "no-such-file.txt") -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
"not found (caught)"
} finally {
"finally always runs"
}
try { 1 / 0 } catch { "error: $($_.Exception.GetType().Name)" }
try { throw [System.ArgumentException]::new("age must be 0-120") } catch [System.ArgumentException] { "ArgumentException: $($_.Exception.Message)" }
Get-Item (Join-Path ([System.IO.Path]::GetTempPath()) "also-missing.txt") -ErrorAction SilentlyContinue
"after SilentlyContinue, `$? is $?"
✅ Verified output
not found (caught) finally always runs error: RuntimeException ArgumentException: age must be 0-120 after SilentlyContinue, $? is False
Files, JSON and CSV
Set-Content and Get-Content handle text; Export-Csv/Import-Csv turn objects into CSV and back; ConvertTo-Json for APIs. Join-Path builds paths for any OS.
$dir = [System.IO.Path]::GetTempPath()
$csv = Join-Path $dir "marks.csv"
@(
[PSCustomObject]@{ Name = "Asha"; Marks = 88 }
[PSCustomObject]@{ Name = "Ravi"; Marks = 95 }
) | Export-Csv $csv -NoTypeInformation
$rows = Import-Csv $csv
$rows | ForEach-Object { "$($_.Name) -> $($_.Marks)" }
"average $(($rows | Measure-Object -Property Marks -Average).Average)"
$rows | ConvertTo-Json -Compress
Remove-Item $csv
"deleted: $(-not (Test-Path $csv))"
✅ Verified output
Asha -> 88
Ravi -> 95
average 91.5
[{"Name":"Asha","Marks":"88"},{"Name":"Ravi","Marks":"95"}]
deleted: True
🌳 Advanced (4)
Recursion and memoization
Functions can call themselves; a script-scope hashtable caches results. [bigint] handles very large numbers.
$script:memo = @{}
function Get-Fib([int]$n) {
if ($n -lt 2) { return [bigint]$n }
if ($script:memo.ContainsKey($n)) { return $script:memo[$n] }
$v = (Get-Fib ($n - 1)) + (Get-Fib ($n - 2))
$script:memo[$n] = $v
return $v
}
((0..9 | ForEach-Object { Get-Fib $_ }) -join " ") + " | fib(90) = " + (Get-Fib 90)
✅ Verified output
0 1 1 2 3 5 8 13 21 34 | fib(90) = 2880067194370816120
Script blocks and pipeline functions
A script block { } is a function value; & runs it. A function with begin/process/end and ValueFromPipeline processes pipeline input one item at a time.
$applyTwice = { param($f, $x) & $f (& $f $x) }
& $applyTwice { param($n) $n * 3 } 2
function Measure-Words {
param([Parameter(ValueFromPipeline)][string]$Line)
begin { $count = 0 }
process { $count += ($Line -split '\s+' | Where-Object { $_ }).Count }
end { "total words: $count" }
}
"the cat sat", "on the mat today" | Measure-Words
$students = @(@{n = "Asha"; m = 88 }, @{n = "Ravi"; m = 95 })
($students | Sort-Object { $_.m } -Descending | ForEach-Object { $_.n }) -join ", "
✅ Verified output
18 total words: 7 Ravi, Asha
Parallel work with ForEach-Object -Parallel
PowerShell 7 runs script blocks on several threads with -Parallel; $using: passes outside variables in. Three 1-second jobs take about 1 second.
$sw = [System.Diagnostics.Stopwatch]::StartNew()
$offset = 100
$results = 1..3 | ForEach-Object -Parallel {
Start-Sleep -Seconds 1
$_ * $_ + $using:offset
} -ThrottleLimit 3
"results: $(($results | Sort-Object) -join ', ')"
"took under 2 s: $($sw.Elapsed.TotalSeconds -lt 2)"
$job = Start-ThreadJob { 6 * 7 }
"thread job result: $(Receive-Job $job -Wait)"
✅ Verified output
results: 101, 104, 109 took under 2 s: True thread job result: 42
Objects, references and copies
Arrays and objects are .NET references: two variables can point to one object. Clone() copies an array; [PSCustomObject].psobject.Copy() copies an object.
$a = @(1, 2, 3)
$b = $a
$c = $a.Clone()
$a[0] = 99
"a $a | b $b | c $c"
$o1 = [PSCustomObject]@{ X = 1 }
$o2 = $o1
$o3 = $o1.psobject.Copy()
$o1.X = 50
"o2.X $($o2.X) (shared) o3.X $($o3.X) (copy)"
"same object: $([object]::ReferenceEquals($o1, $o2))"
✅ Verified output
a 99 2 3 | b 99 2 3 | c 1 2 3 o2.X 50 (shared) o3.X 1 (copy) same object: True
💻 Terminal on my computer
Like a cloud shell, but on your own laptop: install compilers and run real commands from this page through the free GayaGnan agent. It asks you before connecting, installing or running anything.
🛠️ Set up and verify
- Install
winget install Microsoft.PowerShell
brew install --cask powershell
see learn.microsoft.com (Install PowerShell on Linux)
- Editor: Visual Studio Code with PowerShell (Microsoft), PSScriptAnalyzer.
- Create
hello.ps1Write-Output 'Hello, GayaGnan!'
- Run it and check the version
pwsh ./hello.ps1 pwsh -Version
- Health check: paste what your terminal printed.
Install one language at a time. These commands only install or print versions; nothing here deletes files. Versions change: check the official page and note the version you installed.
🧭 The 14-lab path
- 00 · Setup and verify — install the runtime and editor, run hello world, print the version, fix PATH
- 01 · Syntax and trace — follow each line and the value of every variable
- 02 · Logic — conditionals and decision trees
- 03 · Loops — trace tables and loop challenges
- 04 · Functions — break problems down and test each piece
- 05 · Data structures — lists, maps, stacks, queues and trees you can see
- 06 · Debugging — bug cases with a hint ladder
- 07 · Algorithms — search, sort and Big-O comparison
- 08 · Files and data — read and write fixture files 🧪 Bash & PowerShell Automation
- 09 · API or database — talk to a mock API or a sandbox database
- 10 · Testing — write tests and read failing assertions
- 11 · Security — secure coding and dependency hygiene for this language
- 12 · Project — one portfolio mini-project
- 13 · Assessment — quiz, coding test, rubric and an explain-your-answer prompt
📚 Modules
- objects and the pipeline
- variables
- conditions
- loops
- functions
- modules
- error handling
- JSON and CSV
- REST calls to a mock endpoint
- Pester tests
- safe automation
🏗️ Mini-projects
- Synthetic asset report
- Config validator
- Mock cloud tag audit
Projects use synthetic data only.