2

I understood the difference between .Replace() and -replace, but what are -replace and [Regex]::Replace()?

I tested the 2 following codes, but for me the results are the exactly the same.

I also referred to PowerShell Cookbook(O'reilly), and it says

([Regex] is) extremely advanced regular expression replacement

I want to know what [Regex] can but -replace can't.

$line = "Loosen the socket by turning it#counterclockwise."
$line = $line -Replace "([a-z])#([a-z])","`$1 `$2"
$line

# Loosen the socket by turning it counterclockwise.

$line.GetType()
# IsPublic IsSerial Name                                     BaseType
# -------- -------- ----                                     --------
# True     True     String                                   System.Object

$line2 = "Loosen the socket by turning it#counterclockwise."
$line2 = [Regex]::Replace($line3,"([a-z])#([a-z])","`$1 `$2")
$line2

# Loosen the socket by turning it counterclockwise.

$line2.GetType()
# IsPublic IsSerial Name                                     BaseType
# -------- -------- ----                                     --------
# True     True     String                                   System.Object
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
17 minutes
  • 129
  • 5
  • 1
    Try against `$line = "A#b"`, you will see it immediately (`-replace` is case-insensitive by default). Besides, you cannot manipulate a match with a callback when using `-replace`. – Wiktor Stribiżew Sep 14 '18 at 13:20
  • 2
    @WiktorStribiżew as of today (version 6.1) [you can](https://github.com/PowerShell/PowerShell/releases/tag/v6.1.0) ;) – Mathias R. Jessen Sep 14 '18 at 13:28
  • @MathiasR.Jessen Wow. So, only case-sensitivity is left, right? – Wiktor Stribiżew Sep 14 '18 at 13:31
  • 2
    From my perspective it boils down to: use `-replace` until you run into something that doesn't work. Switch to `[regex]::Replace()` when you do. Operator syntax is simpler to write and understand, so stick to that as long as you can. – Ansgar Wiechers Sep 14 '18 at 14:59
  • Possible duplicate of [What's the difference between .replace and -replace in powershell?](https://stackoverflow.com/questions/10184156/whats-the-difference-between-replace-and-replace-in-powershell) – henrycarteruk Sep 14 '18 at 15:03
  • @JamesC: Related, but not a duplicate, because the linked question is about the `[string]` type's `.Replace` (instance) method, not about the `[regex]` type's (static) method of the same name. – mklement0 Sep 14 '18 at 15:07
  • @WiktorStribiżew You can have case sensitivity: `-creplace` – Maximilian Burszley Sep 14 '18 at 15:31
  • @TheIncorrigible1 I know that, the question is not about `-creplace` – Wiktor Stribiżew Sep 14 '18 at 16:15

2 Answers2

3

-Replace is a powershell operator that replaces X with Y and cannot be configured to do anything else.

[Regex] is a .NET class which contains a method called Replace and has many overloads that can configure and control how the string is replaced.

-replace probably uses [Regex]::Replace under the hood.

The reference to the Regex.Replace method contains all the many different ways it can be called.

The methods and properties contained in the Regex class.

henrycarteruk
  • 12,708
  • 2
  • 36
  • 40
The Fish
  • 1,039
  • 5
  • 6
3

The Fish's helpful answer contains good pointers, but let me frame things a little differently, in part inspired by Ansgar Wiechers' comments:

  • PowerShell's -replace operator is a friendly wrapper for the .NET [Regex]::Replace() method.

    • Given that PowerShell is built on the .NET framework, it is a common pattern for PowerShell to surface .NET functionality in a simpler, higher-level fashion.
  • An important difference in default behavior is that -replace is case-INsensitive by default, in line with PowerShell's behavior in general.

    • Use variant -creplace for case-sensitive replacements.
  • -replace only provides a subset of the functionality provided by the various [Regex]::Replace() overloads.

    • The functionality gap has narrowed in PowerShell Core v6.1.0+, which now also offers callback functionality via a script block passed to -replace, thanks to work by Mathias R. Jessen; e.g.,
      '1 + 1 = 2' -replace '\d+', { [int] $_.Value * 2 } yields '2 + 2 = 4' and is the equivalent of:
      [regex]::replace('1 + 1 = 2', '\d+', { param($match) [int] $match.Value * 2 })
  • If -replace is good enough for a given use case, use it rather than [regex]::Replace().

    • The syntax of method calls differs from the rest of PowerShell, and there are subtleties around type conversion and long-term stability of code; it is therefore generally preferable to stick with native PowerShell features (cmdlets and operators), if feasible.

    • However, if -replace doesn't provide the functionality you need, calling [regex]::Replace() directly is a great advanced option; note that Replace() also exists as an instance method, in which case it offers additional functionality - e.g., the ability to limit the number of replacements; e.g.:

      # Replace only the first two 'o' instances.
      PS> $re = [regex] 'o'; $re.Replace('fooo', '@', 2)
      f@@o
      
mklement0
  • 382,024
  • 64
  • 607
  • 775