Skip to content
AgileLogics
6 min read

Regular Expressions

Prerequisites: Operators, Reading and writing text files

PowerShell uses .NET regular expressions throughout: -match, -replace, -split, switch -Regex, and Select-String.

-match and $Matches

$line = 'Order #1042 shipped to London on 2025-04-22'

if ($line -match '#(\d+).* to (\w+) on (\d{4}-\d{2}-\d{2})') {
  "Order: $($Matches[1]), City: $($Matches[2]), Date: $($Matches[3])"
}

if ($line -match '#(?<id>\d+)') {
  "Named group: $($Matches.id)"
}
Order: 1042, City: London, Date: 2025-04-22
Named group: 1042

Named groups ((?<id>...)) make patterns self-documenting.

Finding every match

-match finds only the first match. For all of them, use [regex]:

$text = 'Contact ada@example.com or linus@example.org for access.'
[regex]::Matches($text, '[\w.]+@[\w.]+\w') | ForEach-Object Value
ada@example.com
linus@example.org

-replace with groups

'2025-04-22' -replace '(\d{4})-(\d{2})-(\d{2})', '$3/$2/$1'
'John Smith' -replace '(?<first>\w+) (?<last>\w+)', '${last}, ${first}'
'too    many   spaces' -replace '\s+', ' '
22/04/2025
Smith, John
too many spaces

Use single quotes for the replacement, so PowerShell doesn't treat $1 as a variable.

Select-String: grep for PowerShell

Set-Content app.log @'
INFO  Server started
ERROR Database timeout after 30s
INFO  Request served
ERROR Disk usage at 95%
'@

Select-String -Path app.log -Pattern 'ERROR' | ForEach-Object { "$($_.LineNumber): $($_.Line)" }
Select-String -Path app.log -Pattern '(\d+)(s|%)' | ForEach-Object { $_.Matches[0].Value }
2: ERROR Database timeout after 30s
4: ERROR Disk usage at 95%
30s
95%

Select-String returns match objects with LineNumber, Line, Filename, and Matches. Search many files at once with Get-ChildItem -Recurse -Filter *.log | Select-String 'ERROR'.

Build and test patterns interactively with the Regex Tester.