Regular Expression Actions
In this issue:
If you've been following along the last few issues, and practicing, using regular expressions in PowerShell should not be quite as intimidating. There are a few more basic concepts to cover that should get you through most basic PowerShell usage scenarios. Let's continue learning.
Anchors
One of the more devious, or unpredictable facets of using regular expressions is the idea of a floating match.
PS C:\> "PowerShell is useful." -match "shell" ? $matches : $null
Name Value
---- -----
0 Shell
PS C:\> "Shell is useful." -match "shell" ? $matches : $null
Name Value
---- -----
0 Shell
PS C:\> "Is useful: PowerShell." -match "shell" ? $matches : $null
Name Value
---- -----
0 Shell
As you can see, the regular expression will match anywhere in the string. This isn't necessarily a bad thing, just something you need to be aware of. In some ways, this makes it easy to use regular expressions in PowerShell.
PS C:\> Get-Service | where {$_.DisplayName -match "host"}
Status Name DisplayName
------ ---- -----------
Stopped fdPHost Function Discovery Provider Host
Stopped HgClientService Host Guardian Client Service
Running HNS Host Network Service
Running HvHost HV Host Service
Running jhi_service Intel(R) Dynamic Application Loader Host Interface Service
Stopped PerfHost Performance Counter DLL Host
Stopped upnphost UPnP Device Host
Running vmcompute Hyper-V Host Compute Service
Stopped WdiServiceHost Diagnostic Service Host
Running WdiSystemHost Diagnostic System Host
Stopped WEPHOSTSVC Windows Encryption Provider Host Service
The expression matched anywhere that host was found. But suppose I wanted to only find services where the name ended in host. For that, I can supply an anchor. You can use ^ to anchor the patter match to the beginning of the string. use $ to anchor to the end.
PS C:\> Get-Service | where {$_.DisplayName -match 'host$'}
Status Name DisplayName
------ ---- -----------
Stopped fdPHost Function Discovery Provider Host
Stopped PerfHost Performance Counter DLL Host
Stopped upnphost UPnP Device Host
Stopped WdiServiceHost Diagnostic Service Host
Running WdiSystemHost Diagnostic System Host
Whenever I use the $ anchor, I use single quotes to avoid PowerShell treating it as part of a variable.
> My example is for demonstration purposes. This is not how I would perform this task normally. I could run Get-Service -displayName *host and get the same results, even faster.
And you can combine the anchors. Take a look at these sample files.
PS C:\> dir c:\temp\*sys*
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 3/16/2026 3:03 PM 62782 data-sys.txt
-a--- 2/2/2026 1:25 PM 73428 spectre-system-status.png
-a--- 2/21/2023 3:31 PM 1073152 sysinfo.db
-a--- 6/4/2025 4:29 PM 4407 SysInfo.html
-a--- 6/4/2025 4:29 PM 4407 SysInfo.txt
-a--- 3/16/2026 3:10 PM 6406 SysInfo2.html
-a--- 3/16/2026 3:10 PM 2326 SysInfo3.html
-a--- 3/16/2026 3:05 PM 85658 SysProcess.html
-a--- 7/2/2025 4:25 PM 34553 SysReport.html
-a--- 3/16/2026 3:05 PM 86146 SysService-1.html
I want to get a directly listing by only see files that begin with Sys, end in .html and match either Info or Report in the middle.
PS C:\> dir c:\temp\ -file | Where {$_.name -match '^Sys((Info)|(Report)).*\.html$'}
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 6/4/2025 4:29 PM 4407 SysInfo.html
-a--- 3/16/2026 3:10 PM 6406 SysInfo2.html
-a--- 3/16/2026 3:10 PM 2326 SysInfo3.html
-a--- 7/2/2025 4:25 PM 34553 SysReport.html
In actuality, the better approach would be to split the difference.
PS C:\> dir c:\temp\sys*.html | Where {$_.name -match "(Info)|(Report)"}
Directory: C:\temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 6/4/2025 4:29 PM 4407 SysInfo.html
-a--- 3/16/2026 3:10 PM 6406 SysInfo2.html
-a--- 3/16/2026 3:10 PM 2326 SysInfo3.html
-a--- 7/2/2025 4:25 PM 34553 SysReport.html
The first part of the expression uses early filtering to cut down on the number of files. The Where-Object expression fine-tunes the selection.
However, you need to understand how anchors work because you might be analyzing a text file or some other source that doesn't provide any type of filtering.
PS C:\> Get-Content c:\temp\filelist.txt | Where {$_ -match '^Sys((Info)|(Report)).*\.html$'}
SysInfo.html
SysInfo2.html
SysInfo3.html
SysReport.html
Since I'm parsing a text file, I could also use the pattern with Select-String.
PS C:\> Get-Content C:\temp\filelist.txt | Select-String '^Sys((Info)|(Report)).*\.html$'
SysInfo.html
SysInfo2.html
SysInfo3.html
SysReport.html