- WSL: Start Linux apps in Windows and Windows apps in Linux, access ext4 and NTFS - Mon, Dec 11 2023
- SystoLOCK in review: Logging in to Active Directory with multi-factor authentication without passwords - Tue, Dec 5 2023
- New Group Policy settings in Windows 11 23H2 - Mon, Nov 20 2023
Unlike in Word, Microsoft based PowerShell's RegEx implementation mostly on Perl. Thus, if you have experience with regular expressions, your learning curve in PowerShell will be relatively flat.
Compared to wildcards, regular expressions are much more powerful because they are not just limited to substrings and simple placeholders. For example, you can define ranges (like [a-d]), distinguish between character classes (numeric, alphabetic, whitespace, etc.), or match against the number of occurrences by using various quantifiers. This cheat sheet (PDF) provides a good overview of the RegEx features in PowerShell.
Pattern matching with the -Match operator
PowerShell offers a variety of comparison operators that you can not only apply to numeric values but also to string objects. One of them is -Match, which not only supports literal expressions but also RegEx:
"The regular expression in PowerShell 4.0" -Match "shell\s*(\d)"
This statement results in TRUE. This is something of a surprise because RegEx is usually case sensitive. In the above example, “PowerShell” contains the capital letter “S” whereas the regular expression uses a lower case “s.”
If you need a case sensitive comparison, you can use the -Cmatch operator. In addition, PowerShell supports the -Imatch parameter that works just like -Match. However, as its names implies, it is case insensitive, which helps avoid unwanted side effects.
With complex regular expressions, you often want to know not only whether a pattern matches or not but also to which expression it applies. The $Matches array serves this purpose. The Matches[0] variable contains the entire string that matches the pattern, and the subsequent members of the array store the so-called group matches. These are the subexpressions in parentheses (in the above example (\d)):
A peculiarity of -match and its variants is that it only determines the first match; they disregards additional matches.
Select -String with the parameters -Pattern and -AllMatches
If you want to determine all matches, then the Select-String cmdlet is suitable. It supports the parameter -pattern to which you can pass a regular expression.
Although Select-String also stops after the first match, you can turn off this behavior with the -AllMatches switch:
Help about_regular_expressions | Select-String -Pattern "quanti.*" -AllMatches
If you only want to display the matches, you can iterate over the matches property of the returned MatchInfo object (with % as an alias for the Foreach-Object as in the following example) and then iterate again over the resulting object to extract the Value property.
Help about_reg | Select-String -Pattern "quanti.*" -AllMatches | %{$_.matches} | %{$_.Value}
Search and replace with -Replace
If you don’t just want to find text patterns but also replace them with strings, you can use the -Replace operator. As expected, it requires two arguments, the regular expression and the replacement string that you have to separate with a comma:
“Introduction to PowerShell 4.0” -Replace "\d\.", "5."
In contrast to -Match, the -Replace operator does not return a Boolean value that informs you whether the regular expression matches or not. Instead, it will produce the new string.
Often, you will want to replace a pattern not just with a constant string but with portions of the original string. In those cases, you usually have to capture the text matched inside groups and reuse it in the backreference variables $1, $2, $3, and so on. PowerShell automatically assigns special variables, such as $& (an entire string that matches the pattern).
The following example demonstrates how you can replace the third octet with the value “99” in all IP addresses of the hosts file that start with “192.168.”
$IPs = Get-Content -Path C:\Windows\system32\drivers\etc\hosts $IPs -Replace "192\.168\.\d{1,3}\.(\d{1,3})", '192.168.99.$1'
Because the subpattern of the last octet is the only one that is grouped (it is in parentheses), you can capture it in the backreference variable $1 and reuse it in the new IP address.
Note that the replacement text should be in single quotation marks because PowerShell expands variables in double quotations marks before they are passed to the RegEx engine. As backreference variables are usually not preset, PowerShell will replace the variables in such a case with the empty string.
By the way, unlike the -Match operator, -Replace doesn’t store the matches in the $Match variable.
Split strings with -Split
As its name suggests, the -Split parameter splits strings at defined delimiters into multiple substrings. Typical delimiters are tabs, semicolons, and spaces.
It is more flexible to define the positions where you want to split the string with regular expressions. Check out the example below:
"Chapter 1: Introduction to PowerShell 4.0" -Split "(\d+|\s)"
This command splits the string at every number and whitespace character.
Hi, the RegEx cheatsheet you refer to has moved to:
https://www.cheatography.com/davechild/cheat-sheets/regular-expressions/
Thanks for the very useful article!
StevenP
Thanks for the hint! I changed the link to the RegEx cheatsheet now.