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

SymbolMeaningExampleMatches
.Any single charactera.cabc, a1c, a_c
*Zero or more of previousab*cac, abc, abbc
+One or more of previousab+cabc, abbc (not ac)
?Zero or one of previouscolou?rcolor, colour
^Start of string^HelloString starting with Hello
$End of stringworld$String ending with world
\dAny digit (0-9)\d+1, 42, 999
\wWord character (letter, digit, _)\w+hello, user1, my_var
\sWhitespace\s+space, tab
\DNon-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
|ORcat|dogcat or dog
\bWord boundary\bword\bword (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

PatternMatches
^\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)\bLog 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.

Leave a Comment