How to use regular expression in PowerShell

Brock Bingham candid headshot
Brock Bingham|March 9, 2023
How to use regular expressions in PowerShell hero image.
How to use regular expressions in PowerShell hero image.

Regular expression, commonly referred to as regex, is a powerful tool for those that know how to leverage its robust capabilities. It has a variety of applications, but to the untrained, it can look like hieroglyphics. In this article, we’ll pull back the curtain on regex, decipher its bizarre syntax, and discover how it can improve our PowerShell scripts.

What is regular expression (regex)

Regular expression is a series of characters that define a search pattern. It's used to identify matching text strings. Regular expressions can consist of a single character or a complex combination of characters designed to return broad or very concise results.

Regular expression, which I’ll refer to as regex from this point on (yes, because I’m lazy), works with an extensive list of text editors and scripting languages, including Notepad++, Visual Studio Code, SQL, Python, Perl, Java, PowerShell, and many more. While some systems include their own flavor of regex, others utilize standard regex libraries. PowerShell uses .NET regular expressions.

The information in this article focuses solely on the .NET regex engine. While there are many similarities between regex implementations, there can also be several differences between syntax, features, and behavior.

PowerShell regex reference sheet

If you’re new to regex and come across a complex regex statement, then you know what true confusion feels like.

Regex is a somewhat standardized shorthand language model that uses special characters, sometimes called metacharacters, to define pattern parameters. I say “somewhat” because different applications and languages use different regex models, which can vary slightly.

To the untrained eye, a regex statement may appear as though a cat walked across a keyboard. However, even those familiar with regex may struggle to read patterns, especially if they don’t work with regex consistently. That’s why it’s nice to keep a cheat sheet handy.

Regex Character

Matches

.

Matches any single character except newline.

^

Matches the beginning of a line.

$

Matches the end of a line.

\

Escapes a trailing special character.

*

Matches zero or more times, matching as many times as possible.

+

Matches 1 or more times, matching as many times as possible.

?

Repeat 0 or 1 time, as many times as possible.

??

Repeat 0 or 1 time, 0 if possible.

*?

Repeat 0 or more times, as few as possible.

+?

Repeat 1 or more times, as few as possible.

\w

Matches alphanumeric character [a–z] [A–Z] [0–9] and underscore.

\W

Matches a non-alphanumeric character.

\d

Matches a number character [0–9].

\D

Matches any non-number character.

\s

Matches a whitespace character.

\S

Matches any non-whitespace character.

\n

Matches a newline.

\t

Matches a tab.

\r

Matches a carriage return.

\b

Matches a word boundary between word and nonword characters.

\B

Matches a location that is not a word boundary.

\A

Matches must occur at the beginning of a string.

\Z

Matches must occur at the end of a string or before a newline.

\z

Matches must occur at the end of a string.

\G

Matches must occur at the point the previous match ended.

[abc123…]

Matches any character in brackets.

[^abc123…]

Matches any character not in brackets.

[a-z]

Matches any character in the range of characters.

{n}

Matches exactly n times.

{n,}

Matches at least n times.

{n,m}

Matches at least n times, up to m times.

a|b

Matches either a or b.

(…)

Specifies the pattern as a group.

Utilizing regex in PowerShell

If you’ve spent any significant amount of time with PowerShell, there's a good chance you’ve already used regex. If you’ve matched or replaced a string, you’ve used regex.

Here are some of the PowerShell commands that utilize regex:

  • -match operator

  • -replace operator

  • -split operator

  • Select-String

  • switch statements with the -regex option

Let’s look at a few basic examples of regex usage in PowerShell. Remember, if you’re wondering what a regex special character does, refer to the cheat sheet above or any of the other resources linked below.

Matching patterns in PowerShell with regex

The -match operator identifies input that matches the provided regex pattern. It returns a Boolean value of true if a match is found and false if no match is found. Here is an example of how the -match operator works.

'Elden Ring is an amazing game!' -match 'amazing'

This command returns true because the pattern ‘amazing’ is found in the string ‘Elden Ring is an amazing game!’

This is a PowerShell script demonstrating the use of the -match operator.

Don’t confuse -match with -like. While -match uses regex, -like uses simplified wildcard pattern matching. If we replace -match with -like in the previous example, the command returns false.

This is a PowerShell script that demonstrates the use of the -like operator.

The -like operator is attempting to match the pattern ‘amazing’ one for one. It fails because the sentence contains much more than just ‘amazing. If we wanted the above command to work with the -like operator, we would need to add an asterisk before and after ‘amazing’ for the command to return true.

Here’s a slightly more complex example of utilizing the -match operator.

'Elden Ring won game of the year in 2022.' -match '\d{4}\.$'

The pattern ‘\d{4}\.$’ indicates that we’re looking for four digits or number characters followed immediately by a period. The $ indicates that the match needs to come at the end of the line. If it doesn’t come at the end of the line, the command returns false.

This is a PowerShell script that uses a regex pattern consisting of four digits.

Replacing strings in PowerShell with regex

The -replace operator in PowerShell works much like the -match operator, except when a matching pattern is found, it’s replaced with a substitute. Here’s the basic format of a -replace command:

<input> -replace <regex pattern>, <replacement>

Here’s a simple example of a -replace command that uses variables to store the input.

$halo = 'Halo infinite was great.' $halo -replace 'was great', 'could have been better'
This is a PowerShell script that demonstrates the use of the -replace operator.

It’s important to note that the -replace operator doesn’t overwrite the value stored in the variable. You would need to recast the value of the variable to replace it.

Splitting strings in PowerShell with regex

The -split operator in PowerShell can split strings into substrings. By default, whitespace is used as the delimiter. However, the delimiter can be set to specific characters, strings, or patterns.

Here are some examples of the -split operator in use.

-split 'Red Dead Redemption' 'Red,Dead,Redemption' -split ',' 'RedzDeadzRedemption' -split 'z' 'Red1Dead2Redemption' -split '\d'
This is a PowerShell script that demonstrates the uses of the -split command.

The first example is formatted a bit differently but uses the default whitespace as the delimiter. The second and third examples use ‘,’ and ‘z’ characters as the designated delimiters. The last example uses the ‘\d’ regex special character, meaning any number character is treated as a delimiter.

Utilizing Select-String in PowerShell

The Select-String cmdlet utilizes regex to match input from strings and files. If you have data that needs to be cleaned up and formatted, the Select-String cmdlet is the command for the job. Here’s an example of using the Select-String cmdlet to identify the names of games in a block of text.

$text = "Mass Effect is a great trilogy. Mass Effect 2 was my favorite, followed by Mass Effect 3. Mass Effect 1 was good, but the gameplay was a bit clunky. mass effect 4 was the game we never got (Andromeda doesn't count!)." $games = $text | Select-String -Pattern 'Mass\sEffect\s\d' -CaseSensitive -AllMatches $games.Matches.Value
This PowerShell script demonstrates the use of the Select-String cmdlet.

In this example, we piped the contents of the $text variable to the Select-String cmdlet. Using the -Pattern parameter, we set the regex pattern as ‘Mass\sEffect\s\d’ and set the pattern to be case sensitive with the -CaseSensitive parameter. We also included the -AllMatches parameter because only the first match in each line returns by default. The -AllMatches parameter returns all matches found. We’ve assigned the results of the command to the $games variable, then called the variable with the .Matches.Value property to return just the matched values. Notice that ‘mass effect 4’ was not returned because it did not match the case sensitivity requirement.

Here's another example of the Select-String cmdlet in use. In this example, we have a text file containing random employee data, including the name, username, and employee ID of several employees. We want to extract the usernames contained in the file, but the file is not in a very functional format. We can use the Select-String command to retrieve only the data we’re looking for and export it to a CSV file.

Here is what our original source file looks like.

This is an CSV file containing fictional names, usernames, and employee IDs.

Here is the script we’ll use to extract the usernames from the text file.

$file = Get-ChildItem 'C:\Temp\SFEmployeeInfo.txt' $username = Select-String -Path $file -Pattern 'username:\s(.*)$' | ForEach-Object {$_.Matches.Groups[1].Value} $userNames = $username.ToLower() | Select-Object @{Name='Name';Expression={$_}} $userNames | Export-Csv -Path 'C:\Temp\Usernames.csv' -NoTypeInformation

In this script, we’ve assigned our text file to the $file variable. Then we use the Select-String parameter with the pattern ‘username:\s(.*)$’ to match the usernames from the file. Next, we pipe the results to the For-EachObject to return just the matched values (in this case, just the names). Then we convert all the usernames to lowercase format before converting the returned string object to a new object with a Name parameter. By default, a string object only has a length property, which is what is written to the CSV file if we don’t convert it. Lastly, we export data to a CSV file.

Here is the resulting CSV file.

A CSV file containing the results of a PowerShell script that pulled the usernames from another CSV file.

Using switch statements with the -Regex parameter

The switch statement in PowerShell uses exact matching by default, but we can employ the -Regex option to force it to use regex instead. Switch statements are great for evaluating multiple conditions.

Here’s what the syntax of a simple switch statement that utilizes the -Regex parameter looks like.

switch -Regex (<test-expression>){ <condition1> {<action>} <condition2> {<action>} }

Here’s an example of a switch statement that moves user accounts into their corresponding OU depending on the department information contained in a CSV file. This is the CSV file used in this example:

An example CSV file containing names, departments, and email addresses of fictional users.

And here is the script:

$users = Import-CSV -Path 'C:\Temp\User Info.csv' foreach ($user in $users){ switch -Regex ($user.Department){ 'facilities|fac' { Get-ADUser -Identity $user.Name | Move-ADObject -TargetPath "OU=Facilities,DC=nintendo,DC=com" Write-Host $user.Name 'has been moved to the Facilities OU' } 'management|mgt'{ Get-ADUser -Identity $user.Name | Move-ADObject -TargetPath "OU=Management,DC=nintendo,DC=com" Write-Host $user.Name 'has been moved to the Management OU' } 'research' { Get-ADUser -Identity $user.Name | Move-ADObject -TargetPath "OU=Research,DC=nintendo,DC=com" Write-Host $user.Name 'has been moved to the Research OU' } 'sales'{ Get-ADUser -Identity $user.Name | Move-ADObject -TargetPath "OU=Sales,DC=nintendo,DC=com" Write-Host $user.Name 'has been moved to the Sales OU' } 'administration|adm'{ Get-ADUser -Identity $user.Name | Move-ADObject -TargetPath "OU=Administration,DC=nintendo,DC=com" Write-Host $user.Name 'has been moved to the Administration OU' } Default { Write-Host $user.Name 'does not have a matching department' } } }

To summarize, this script is looking at the department value for each CSV entry and comparing it to the regex statements. When a match is made, the user account moves to the matching OU and a corresponding message displays. If a department does not match any regex statement, a message indicates that the user does not have a matching department.

A PowerShell script that pulls in user data from a CSV file and uses that information to move users to their correct OUs in Active Directory.

While this example is certainly effective, it doesn’t rely on complex regex patterns because it doesn’t have to. Your regex patterns need to meet only your requirements. In this example, the requirements were simple, and the patterns could match the information contained in the CSV file almost exactly.

Here’s another example where you would want to ensure the evaluated data is formatted correctly. In this example, we’re asking a user to input a valid email address or phone number.

$userInput = Read-Host -Prompt 'Input your email address ([email protected]) or phone number (123-456-7890)' switch -regex ($userInput){ '^\w+\.??\w*@\w+\.\w+$'{ Write-Host "You've entered an email address" } '\d{3}-\d{3}-\d{4}' { Write-Host "You've entered a valid phone number" } Default { Write-Host "The information you provided was not a valid email address or phone number" } }
A PowerShell script that uses regex to validate user input to match phone numbers or email addresses.

If a user inputs a valid email address, it’s matched against the regex pattern '^\w+\.??\w*@\w+\.\w+$.' If they enter a valid phone number, it’s validated against the regex pattern '\d{3}-\d{3}-\d{4}.' If the input is not valid, the Default value is returned. In this case, a message informs the user the input was not valid.

Other regex resources

Regex is not for the faint of heart, but there are tons of great resources available when you need help. Here are some terrific regex resources that can help both regex beginners and regex pros.

  • Regex Hero reference sheet: The Regex Hero reference sheet, or cheat sheet, is a great resource for quickly identifying regex characters, their uses, and their meanings.

  • Regex Hero .NET tester: This is another great resource from Regex Hero. The .NET tester is a simple application that lets you quickly test out your regex statements.

  • Microsoft’s Regex quick reference sheet: If you prefer to go straight to the source, Microsoft’s regex reference sheet is what you’re looking for. Personally, I prefer the formatting of Regex Hero’s reference sheet, but Microsoft’s is very thorough.

  • regex101: Regex101 is a dedicated web portal you can use to test your expressions quickly. Regex101 also provides helpful explanations, matching information, and reference data.

  • Regex subreddit: The regex subreddit is a great place to get answers for all your regex questions.

  • PowerShell subreddit: With over 200,000 members, the PowerShell subreddit is brimming with some of the smartest people out there. If you need help with PowerShell and regex, this forum gets you the answers you need quickly.

Regex is powerful but complex

There is so much you can do with regex. You can parse files, scrape websites, validate input, and so much more. However, it’s complex. If you don’t regularly use it, you’ll soon forget much of what you learned. That’s why there’s no shame in frequently utilizing the resources above.

If you’re looking for powerful tools that aren’t complex, check out PDQ Deploy and Inventory. This powerful combination can help you manage your endpoints and automate deployments with minimal effort. Try PDQ Deploy and Inventory for free for 14 days.

Brock Bingham candid headshot
Brock Bingham

Born in the '80s and raised by his NES, Brock quickly fell in love with everything tech. With over 15 years of IT experience, Brock now enjoys the life of luxury as a renowned tech blogger and receiver of many Dundie Awards. In his free time, Brock enjoys adventuring with his wife, kids, and dogs, while dreaming of retirement.

Related articles