6

How can you replace the last occurrence of a substring in a string?

Matt
  • 45,022
  • 8
  • 78
  • 119
nickm
  • 119
  • 1
  • 1
  • 8

3 Answers3

12

Regular Expressions can also perform this task. Here is an example of one that would work. It will replace the last occurrence of "Aquarius" with "Bumblebee Joe"

$text = "This is the dawning of the age of Aquarius. The age of Aquarius, Aquarius, Aquarius, Aquarius, Aquarius"
$text -replace "(.*)Aquarius(.*)", '$1Bumblebee Joe$2'
This is the dawning of the age of Aquarius. The age of Aquarius, Aquarius, Aquarius, Aquarius, Bumblebee Joe

The greedy quantifier ensure that it take everything it can up until the last match of Aquarius. The $1 and $2 represent the data before and after that match.

If you are using a variable for the replacement you need to use double quotes and escape the $ for the regex replacements so PowerShell does not try to treat them as a variable

$replace = "Bumblebee Joe"
$text -replace "(.*)Aquarius(.*)", "`$1$replace`$2"
Matt
  • 45,022
  • 8
  • 78
  • 119
  • It seems to work only with the replacement string being a literal. – nickm Feb 10 '15 at 17:56
  • That is only the case since it is enclosed in single quotes. I can update the answer to account for this. – Matt Feb 10 '15 at 18:05
  • Hmm, didn't seem to work for a multi-line string for some reason. It ended up replacing all instances still. – sonjz Mar 03 '15 at 02:37
  • 1
    @sonjz if the string is multiline then you could use single line mode. `"(?s)(.*)Aquarius(.*)", '$1Bumblebee Joe$2'` – Matt Mar 03 '15 at 13:07
  • Thanks @Matt, joy acheived! I was having issues with a .NET .csproj file, works now, sharing my solution as csproj is finicky: $file = Get-Content file.csproj -Raw ; $newFile = $file -replace "(?s)(.*)XXX(.*)", "`$1$replaceVar`$2" ; $newFile | Out-File -Encoding UTF8 "new.csproj" ; – sonjz Mar 03 '15 at 17:00
  • How-to escape a number e.g. `$replace = "6th Aquarius"`? Results to `$16th Aquarius`… – JosefZ Jun 01 '17 at 23:23
  • Why do you need to escape the number? – Matt Jun 01 '17 at 23:30
  • Out of curiosity. Answered https://superuser.com/questions/1215093 however I'd like apply your approach… – JosefZ Jun 01 '17 at 23:34
  • @JosefZ "Escape" the `6` by escaping the capture id instead ``"`${1}6th..."``. @Matt, the number `6` needs to be escaped because it is not supposed to be part of identifying a capture group in the result of the regex, but the string expansion `""` is treating it thus. – Josh Gust Dec 21 '18 at 15:09
  • Does anyone have qualms about using `\Z` for multiline strings. I've seen it elsewhere, and used it too, but I'm not sure if it's better than using `(?s)`. – Josh Gust Dec 21 '18 at 15:13
  • @Matt how do I format the command to use a regex in place of Aquarius between the two (.*) as the first parameter? I basically want to replace the last formatted date in the string, so I am trying to get something like: $text -replace "(.*)`'(19|20)\d\d[- /.]([1-9]|0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])'`(.*)", '$1`$CurrentDate`$2' – nollaf126 Aug 16 '22 at 20:23
5

Using the exact same technique as I would in C#:

function Replace-LastSubstring {
    param(
        [string]$str,
        [string]$substr,
        [string]$newstr
    )

    return $str.Remove(($lastIndex = $str.LastIndexOf($substr)),$substr.Length).Insert($lastIndex,$newstr)
}
Community
  • 1
  • 1
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
1

print(str1[::-1].replace("xx","rr",1)[::-1])

pbeginner
  • 13
  • 4