Home > front end >  Powershell replace operator unexpectedly replaces twice when using asterisk metacharacter
Powershell replace operator unexpectedly replaces twice when using asterisk metacharacter

Time:08-17

Using powershell on Windows, when I use the following simple regular expression to remove any space characters at the end of the string and also append a period, I get duplication of the replacement string when there are spaces. Almost as if the spaces and the end-of-line is matched separately:

PS C:\>  "walk along the edge"   -replace ' *$',"s."
walk along the edges.
PS C:\>  "walk along the edge "  -replace ' *$',"s."
walk along the edges.s.
PS C:\>  "walk along the edge  " -replace ' *$',"s."
walk along the edges.s.

But I expected a more consistent behavior, like this:

$ echo "walk along the edge"   | sed "s/ *$/s./"
walk along the edges.
$ echo "walk along the edge "  | sed "s/ *$/s./"
walk along the edges.
$ echo "walk along the edge  " | sed "s/ *$/s./"
walk along the edges.

This is consistent between PS v7.2.5 and 4.1, both on Windows. Referencing standard GNU sed on RHEL-flavored linux, if that matters. I tried some parenthesis to "force" grouping, and escaping the dollar sign, to no avail.

How do I force the entire matching expression to be evaluated as one big match, in powershell?

Adding an extra space (or using the metacharacter rather than *) is not quite what is required:

PS C:\>  "walk along the edge   " -replace '  *$',"s."
walk along the edges.
PS C:\>  "walk along the edge"   -replace '  *$',"s."
walk along the edge

Although it solves all the cases where there is a space, it fails for the case where there is not a space.

CodePudding user response:

You can add a boundary before the spaces and this returns correctly every time.

PS C:\Users\TMTech> "walk along the edge"   -replace '\b *$',"s."
walk along the edges.

PS C:\Users\TMTech> "walk along the edge "  -replace '\b *$',"s."
walk along the edges.

PS C:\Users\TMTech> "walk along the edge  " -replace '\b *$',"s."
walk along the edges.

CodePudding user response:

You can force the single match by capturing the preceding nonspace character, like this:

"walk along the edge      "   -replace '(.) *$','$1s.'
  • Related