PowerShell regex (regular expressions) lets you match, extract, replace and split text by pattern. The operators -match, -replace and -split all take a regex, and $Matches holds what -match found:
$text = 'Order ORD-5812 ships to Austin, TX'
$text -match 'ORD-(\d+)'
"Whole match: $($Matches[0])"
"Order number: $($Matches[1])"
Output:
True
Whole match: ORD-5812
Order number: 5812

Below I cover case sensitivity, named groups, replacing, splitting, finding every match, Select-String and switch -Regex. Every example ran in PowerShell 7.6 and 5.1, and all the data is made up.
Regex basics in PowerShell
PowerShell uses the .NET regex engine. A few tokens cover most everyday patterns:
| Token | Matches | Example |
|---|---|---|
| \d | One digit | \d{4} matches 2026 |
| \w | Letter, digit or underscore | \w+ matches Austin |
| \s | Whitespace | \s+ matches spaces and tabs |
| . | Any character except a newline | a.c matches abc |
| ^ and $ | Start and end of the string | ^ORD matches at the start |
| ( ) | Capture group | ORD-(\d+) captures 5812 |
| [ ] | Any one character in the set | [;,] matches ; or , |
Microsoft’s regular expression quick reference lists every token.
-match is case-insensitive, -cmatch isn’t
Like most PowerShell operators, -match ignores case. Use -cmatch when case matters:
'INVOICE inv-20431' -match 'INV-\d+'
'INVOICE inv-20431' -cmatch 'INV-\d+'
Output:
True
False
The same rule applies to -replace and -creplace, and -split and -csplit. The -match operator in depth covers matching against arrays.
Capture data with named groups
Named groups, written (?<Name>…), make a pattern easier to read and the results easier to use. Here I break a log line into parts:
$line = '2026-09-14 08:16:44 ERROR [Billing] Card declined for order ORD-5812'
$pattern = '^(?<Date>\S+) (?<Time>\S+) (?<Level>\w+)\s+\[(?<Area>\w+)\] (?<Message>.+)$'
if ($line -match $pattern) {
"Level: $($Matches.Level)"
"Area: $($Matches.Area)"
"Message: $($Matches.Message)"
}
Output:
Level: ERROR
Area: Billing
Message: Card declined for order ORD-5812

Each group name becomes a key in $Matches. Extracting text between delimiters shows more capture patterns.
Replace text with -replace
-replace takes a pattern and a replacement, and $1, $2 refer to your groups. This reformats phone numbers written three different ways:
$phones = '512-555-0147', '214.555.0199', '713 555 0123'
$phones -replace '^(\d{3})[-. ](\d{3})[-. ](\d{4})$', '($1) $2-$3'
Output:
(512) 555-0147
(214) 555-0199
(713) 555-0123

Put the replacement in single quotes. In double quotes, PowerShell would treat $1 as a variable before the regex sees it. Replacing text in strings covers plain-text replacements too.
Split on a pattern with -split
-split accepts a regex, so you can split on several separators at once and trim spaces at the same time:
'Austin; Dallas,Houston ; El Paso' -split '\s*[;,]\s*'
Output:
Austin
Dallas
Houston
El Paso
The pattern \s*[;,]\s* means any spaces, then a semicolon or comma, then any spaces. Splitting strings in PowerShell covers more options.
Find every match with [regex]::Matches
-match stops at the first match. To get all of them, use the .NET Regex class:
$text = 'Contact sales@example.com or support@example.com, not help@example'
$found = [regex]::Matches($text, '\b[\w.-]+@[\w-]+\.\w+\b')
"Found $($found.Count) email addresses:"
$found.Value
Output:
Found 2 email addresses:
sales@example.com
support@example.com
help@example isn’t matched, because the pattern needs a dot and a domain ending after the @.
Search files with Select-String
Select-String runs a regex against every line of a file, like grep. Here I pull the order number from each error line in a log:
Select-String -Path C:\psfaqs\Regex\app.log -Pattern 'ERROR.*(ORD-\d+)' |
ForEach-Object { "Line $($_.LineNumber): $($_.Matches[0].Groups[1].Value)" }
Output:
Line 2: ORD-5812
Line 4: ORD-5815
Each result has the line number and a Matches collection with your groups. Finding text patterns with Select-String goes further.
Branch on patterns with switch -Regex
switch -Regex tests a value against several patterns and runs the first block that matches:
foreach ($id in 'ORD-5812', 'INV-20431', 'RMA-77') {
switch -Regex ($id) {
'^ORD-\d+$' { "$id is an order"; break }
'^INV-\d+$' { "$id is an invoice"; break }
default { "$id is unknown" }
}
}
Output:
ORD-5812 is an order
INV-20431 is an invoice
RMA-77 is unknown
Without break, switch keeps testing the remaining patterns, which is useful when one value can match more than one.
Escape special characters
Characters like ( ) . \ and $ have special meanings in regex. [regex]::Escape() makes a literal string safe to use as a pattern:
$path = 'C:\Reports\Q3 (2026).xlsx'
$pattern = [regex]::Escape('Q3 (2026)')
"Escaped pattern: $pattern"
"Match found: $($path -match $pattern)"
Output:
Escaped pattern: Q3\ \(2026\)
Match found: True
Always escape user input or file names before putting them into a pattern. Microsoft covers this and more in about_Regular_Expressions.
Frequently Asked Questions
How do I use regex in PowerShell?
Use the -match, -replace and -split operators, or Select-String for files. They all accept .NET regular expressions.
Is PowerShell -match case-sensitive?
No. -match ignores case. Use -cmatch for a case-sensitive match.
How do I get the captured group from -match?
Read the $Matches variable after a successful -match. $Matches[1] is the first group, and named groups use their names.
How do I find all regex matches in a string?
Use [regex]::Matches($text, $pattern). -match only returns the first match.
How do I escape special characters in a PowerShell regex?
Pass the literal text to [regex]::Escape(), or put a backslash before each special character.
Keep going with text processing:
- The -match operator
- Replace text in strings
- Find text patterns with Select-String
- Escape special characters in variables
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.