Regex Capturing with PowerShell
In this issue:
A few weeks ago I wrote a few newsletters on regular expression fundamentals. This isn't specifically a PowerShell topic, but it is something that you will find very helpful in your scripting projects. And PowerShell makes it very easy to use. You just have to learn the syntax for the regex task at hand. Today, I want to cover a few advanced topics.
[Regex]
As I showed last time, you can define a regular expression pattern as a string when using a regular expression operator like -match.
PS C:\> dir c:\work\ -file | where name -match "\.ps[dm]1$"
Directory: C:\work
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 7/18/2025 11:35 AM 7686 m.psd1
-a--- 3/11/2026 3:24 PM 2886 PSWorkItem.psd1
-a--- 3/11/2026 3:26 PM 7193 PSWorkItem.psm1
Can you decipher the pattern? I am looking for files where the name ends in a literal period, the letters ps followed by either d or m and then 1.
Another way to define a regular expression pattern is to use the [regex] type accelerator. Assuming you don't need any advanced regular expression features which most people rarely need, you can create a regex object like this:
PS C:\> [regex]$rx = "\.ps[dm]1$"
PS C:\> $rx
Options RightToLeft MatchTimeout
------- ----------- ------------
None False -00:00:00.0010000
PS C:\> $rx.GetType().FullName
System.Text.RegularExpressions.Regex
This object has many methods you will want to take advantage of.
PS C:\> $rx | Get-Member -MemberType Method | Select Name,Definition
Name Definition
---- ----------
Count int Count(string input), int Count(System.ReadOnlySpan[char…
EnumerateMatches System.Text.RegularExpressions.Regex+ValueMatchEnumerator E…
EnumerateSplits System.Text.RegularExpressions.Regex+ValueSplitEnumerator E…
Equals bool Equals(System.Object obj)
GetGroupNames string[] GetGroupNames()
GetGroupNumbers int[] GetGroupNumbers()
GetHashCode int GetHashCode()
GetObjectData void ISerializable.GetObjectData(System.Runtime.Serializati…
GetType type GetType()
GroupNameFromNumber string GroupNameFromNumber(int i)
GroupNumberFromName int GroupNumberFromName(string name)
IsMatch bool IsMatch(string input), bool IsMatch(string input, int …
Match System.Text.RegularExpressions.Match Match(string input), S…
Matches System.Text.RegularExpressions.MatchCollection Matches(stri…
Replace string Replace(string input, string replacement), string Re…
Split string[] Split(string input), string[] Split(string input, …
ToString string ToString()
Let me re-write my first example.
PS C:\> dir c:\work -file | where {$rx.IsMatch($_.Name)}
Directory: C:\work
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 7/18/2025 11:35 AM 7686 m.psd1
-a--- 3/11/2026 3:24 PM 2886 PSWorkItem.psd1
-a--- 3/11/2026 3:26 PM 7193 PSWorkItem.psm1
The IsMatch() method returns a boolean value.
This makes it easy to filter file names, although I wish there were a way to filter with regular expressions using Get-ChildItem. One thing you might do, especially if the folder has thousands of files is to filter where you can with Get-ChildItem and then apply a more granular filter with Where-Object.
dir c:\work -file -filter *.ps* | where {$rx.IsMatch($_.Name)}
The number of files I'm processing is small, but this did improve performance by 50%.
You can also use the regex object to get match information.
PS C:\> $rx.Match("c:\foo\bar\demo.psm1")
Groups : {0}
Success : True
Name : 0
Captures : {0}
Index : 15
Length : 5
Value : .psm1
ValueSpan :
Invoking Regex Methods
Where this really gets useful is when you want to use a regex method like splitting or replacing. There's nothing wrong with using the native operator.
PS C:\> "PowerShell" -split "[aeiou]"
P
w
rSh
ll