Regular Expressions are a -replace's best friend

Are you familiar with PowerShell’s -replace operator?

"John Jones" -replace "Jones","Smith"

Most folks are aware of it, and rely on it for straightforward string replacements like this one. But not very many people know that -replace also does some amazing stuff using regular expressions.

"," -replace "\.\d{2}\.","10"

That’d change the input string to “,,” replacing all occurrences of two digits, between periods, to 10. The 12 would be skipped because it isn’t followed by a period, as specified in the pattern. Note that all occurrences are replaced, in keeping with the usual operation of -replace.
The operator can also do capturing expressions, and this is where it gets really neat-o.

"Don Jones" -replace "([a-z]+)\s([a-z]+)",'$2, $1'

Here, I’ve specified two capturing expressions in parentheses, with a space character between them. PowerShell will capture the first to $1, and the second to $2. Those aren’t actually variables, which is important. In my replacement string, I put $2 first, followed by a comma, a space, and $1. The resulting string will be “Jones, Don”. It’s important that my replacement string be in single quotes. In double quotes, the shell will try and treat $1 and $2 as variables, instead of using them as captured regex placeholders. I kinda wish they’d used something other than a $ for the captured placeholders, so that they didn’t look like variables, but the syntax is in keeping with regex standards.
I think it’s cool to see all the places a regex can be put to use. The -split operator also supports regex syntax as a way of specifying the separator that will be used to break a string into components, so you’re not limited to splitting just on a single character like a comma.
Apart from the well-known -match operator and the Select-String command, where else have you used a regex in PowerShell?

7 Responses to " Regular Expressions are a -replace's best friend "

  1. Dave Wyatt says:

    Aside from the uses you’ve already listed, I use regular expressions from time to time in switch blocks, and with the -split operator.

  2. Dave Wyatt says:

    On a side note, this operation:
    “,” -replace “\.\d{2}\.”,”10″
    doesn’t just change the numbers, it also removes the periods. You’d need to use “.10.” as the replace string to make sure they remained, or use lookahead / lookbehind assertions in the pattern so the periods were checked, but weren’t actually part of the match:
    “,” -replace “\.\d{2}\.”,”.10.”
    “,” -replace “(?<=\.)\d{2}(?=\.)","10"
    Just putting the periods in the replace string is easier to read, in this case, but the lookahead / lookbehind assertions can be useful for some tricky problems.

  3. Hi,
    I’m trying to use this to change the output of the line below from Computername\Username, to simply Username
    Get-wmiobject win32_computersystem | select username
    When I use the code below, the output is @{username=\Username}
    $User= get-wmiobject win32_computersystem -computer $ComputerName2.text | select username
    $ID= $User-replace “Computername”, “”
    Where am I going wrong on this one?

    • Ken Row says:

      Part of the problem is that $user, when presented to -replace, is wrapped by “@{” and “}”.
      Another part of the problem is that you didn’t include the “” in your search pattern.
      One way to approach this would be to first eliminate everything up to the , then do another replace to eliminate the }:

      $id=$user -replace "^.*\", "" -replace "}", ""

      In my version of Powershell, I don’t seem to have the ability to use capturing expressions, as referenced in the above article. If I did, I could get by with just one -replace (note: I’ve not tried this as I don’t have capturing expressions):

      $id=$user -replace "^.*\(.*)}$", "$1"
  4. Note you can use double quotes in the 2nd half of the -replace operation when using capturing groups if you escape the dollar signs with the backtick character. This allows you to use capture groups and variable expansion together should you so wish.
    For example:

    $mytext = "The time is: "
    (get-date).tostring() -replace "S+? ([d:]+)","$mytext `$1"
    #Outputs "The time is:  15:59:13"
    • dragon788 says:

      Thanks David, I was really sweating having to figure out nesting quotes to get a match and an arbitrary string in my replace, you saved me the headache of testing the many variants.

  5. […] page, which is where he got the idea from. I tried to search for more info on this and came across this post by Don Jones and this Wiki page on […]