PowerShell Regular Expressions
A regular expression (regex) is a pattern used to search, match, and manipulate text. In PowerShell, regex powers log analysis, input validation, data extraction, and string transformation. Think of a regex as a very precise search query — instead of searching for the exact word "error", a regex can find any line that starts with a date, followed by the word "error", followed by any message.
Basic Regex Symbols
| Symbol | Meaning | Example | Matches |
|---|---|---|---|
| . | Any single character | a.c | abc, a1c, a_c |
| * | Zero or more of previous | ab*c | ac, abc, abbc |
| + | One or more of previous | ab+c | abc, abbc (not ac) |
| ? | Zero or one of previous | colou?r | color, colour |
| ^ | Start of string | ^Hello | String starting with Hello |
| $ | End of string | world$ | String ending with world |
| \d | Any digit (0-9) | \d+ | 1, 42, 999 |
| \w | Word character (letter, digit, _) | \w+ | hello, user1, my_var |
| \s | Whitespace | \s+ | space, tab |
| \D | Non-digit | \D+ | abc, hello |
| [abc] | Any character in set | [aeiou] | a, e, i, o, u |
| [^abc] | Any character NOT in set | [^aeiou] | b, c, d, f… |
| {n} | Exactly n times | \d{4} | 2026 |
| {n,m} | Between n and m times | \d{2,4} | 12, 123, 9999 |
| ( ) | Capture group | (\d+)-(\d+) | Captures parts separately |
| | | OR | cat|dog | cat or dog |
| \b | Word boundary | \bword\b | word (not password) |
The -match Operator
-match checks if a string contains a pattern. It returns True or False. When it matches, captured groups are stored in the automatic variable $Matches.
# Simple match
"PowerShell 7.4.0" -match "\d+\.\d+\.\d+" # True
# Check email format
$email = "user@company.com"
$email -match "^\w+@\w+\.\w{2,}" # True
# Check for digits
"ABC123" -match "\d" # True
"ABC" -match "\d" # False
# Case-insensitive by default
"HELLO" -match "hello" # True
# Case-sensitive
"HELLO" -cmatch "hello" # False
$Matches – Capture Groups
After a successful -match, the $Matches variable holds the matched content. $Matches[0] is the full match. Numbered keys hold individual capture groups.
$logLine = "2026-03-21 10:30:45 ERROR Database connection failed"
if ($logLine -match "^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+) (.+)$") {
Write-Host "Date: $($Matches[1])"
Write-Host "Time: $($Matches[2])"
Write-Host "Level: $($Matches[3])"
Write-Host "Message: $($Matches[4])"
}
Output:
Date: 2026-03-21
Time: 10:30:45
Level: ERROR
Message: Database connection failed
Named Capture Groups
Named groups use (?<name>...) syntax, making matches easier to read in code.
$ipLine = "Connected from 192.168.1.55 at port 443"
if ($ipLine -match "(?\d{1,3}(\.\d{1,3}){3}).*port (?\d+)") {
Write-Host "IP Address: $($Matches['ip'])"
Write-Host "Port: $($Matches['port'])"
}
Output:
IP Address: 192.168.1.55
Port: 443
The -replace Operator
-replace finds a pattern and substitutes it with replacement text. Use $1, $2 to reference captured groups in the replacement.
# Simple replacement
"Hello World" -replace "World", "PowerShell"
# Output: Hello PowerShell
# Replace digits with X
"Phone: 9876543210" -replace "\d", "X"
# Output: Phone: XXXXXXXXXX
# Remove all whitespace
" trim me " -replace "\s+", ""
# Output: trimme
# Reformat a date using capture groups
$date = "21/03/2026"
$date -replace "(\d{2})/(\d{2})/(\d{4})", "$3-$2-$1"
# Output: 2026-03-21
# Remove HTML tags
$html = "Hello World"
$html -replace "<[^>]+>", ""
# Output: Hello World
The -split Operator with Regex
# Split by any whitespace
"one two three" -split "\s+"
# Output: one two three (as array)
# Split by comma or semicolon
"a,b;c,d" -split "[,;]"
# Output: a b c d
# Split by one or more digits
"abc123def456ghi" -split "\d+"
# Output: abc def ghi
Select-String – Search Files with Regex
Select-String is the PowerShell equivalent of grep. It searches files or text for lines matching a regex pattern.
# Search a file for lines containing "ERROR"
Select-String -Path "C:\Logs\app.log" -Pattern "ERROR"
# Case-insensitive search
Select-String -Path "C:\Logs\app.log" -Pattern "error" -CaseSensitive:$false
# Search multiple files
Select-String -Path "C:\Logs\*.log" -Pattern "timeout"
# Search and show surrounding lines (context)
Select-String -Path "C:\Logs\app.log" -Pattern "CRITICAL" -Context 2, 2
# Show only the matching part (not the full line)
Select-String -Path "C:\Logs\app.log" -Pattern "\d{4}-\d{2}-\d{2}" |
ForEach-Object { $_.Matches.Value }
Search String Arrays
$logs = @(
"2026-03-21 INFO Service started",
"2026-03-21 ERROR DB connection failed",
"2026-03-21 WARN High memory usage",
"2026-03-21 ERROR Timeout exceeded"
)
$errors = $logs | Select-String -Pattern "ERROR"
$errors | ForEach-Object { Write-Host $_.Line }
Output:
2026-03-21 ERROR DB connection failed
2026-03-21 ERROR Timeout exceeded
Using [regex] Class Directly
# Create a regex object for reuse
$pattern = [regex]"\b\d{10}\b" # Exactly 10-digit numbers
$text = "Call us at 9876543210 or 1234567890 for support."
$matches = $pattern.Matches($text)
foreach ($m in $matches) {
Write-Host "Found number: $($m.Value)"
}
Output:
Found number: 9876543210
Found number: 1234567890
# Replace all matches
$result = $pattern.Replace($text, "XXXXXXXXXX")
Write-Host $result
# Output: Call us at XXXXXXXXXX or XXXXXXXXXX for support.
Common Regex Patterns Reference
| Pattern | Matches |
|---|---|
| ^\d{4}-\d{2}-\d{2}$ | Date: 2026-03-21 |
| ^\w+@\w+\.\w{2,}$ | Email: user@domain.com |
| ^\d{1,3}(\.\d{1,3}){3}$ | IP address: 192.168.1.1 |
| ^https?:// | URL starting with http or https |
| ^\+?\d[\d\s\-]{8,14}\d$ | Phone number |
| ^[A-Z][a-zA-Z\s]+$ | Proper name (starts with uppercase) |
| \b(ERROR|WARN|CRITICAL)\b | Log severity level |
| [a-fA-F0-9]{6} | Hex color code: ff5733 |
Real-World Example – Extract Errors from Log File
$logPath = "C:\Logs\application.log"
$outputPath = "C:\Reports\errors_$(Get-Date -Format 'yyyyMMdd').csv"
$results = Select-String -Path $logPath -Pattern "^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) ERROR (.+)$" |
ForEach-Object {
if ($_.Line -match "^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) ERROR (.+)$") {
[PSCustomObject]@{
Date = $Matches[1]
Time = $Matches[2]
Message = $Matches[3]
}
}
}
$results | Export-Csv -Path $outputPath -NoTypeInformation
Write-Host "Errors exported: $($results.Count) records → $outputPath"
Summary
Regular expressions in PowerShell unlock precise text matching and transformation. The -match operator checks patterns and stores capture groups in $Matches. Named groups make captures readable. The -replace operator performs pattern-based substitutions with group references. The -split operator splits strings on regex patterns. Select-String searches files and arrays like a powerful grep utility. The [regex] class provides reusable compiled patterns for high-performance matching. Together, these tools handle log parsing, data validation, text extraction, and bulk text transformations that no simple string method can accomplish.
