Use a function in Powershell replace
I'm trying to replace part of a string in Powershell. However, the replacement string is not hardcoded, it's calculated from a function:
$text = "the image is -12345-"
$text = $text -replace "-(\d*)-", 'This is the image: $1'
Write-Host $text
This gives me the correct result: "This is the image: 12345"
Now, I want to include the base64 encoded image. I can read the image from the id. I was hoping the following would work, but it doesn't:
function Get-Base64($path)
{
[convert]::ToBase64String((get-content $path -encoding byte))
}
$text -replace "-(\d*)-", "This is the image: $(Get-Base64 '$1')"
The reason that it doesn't work, is because it first passes $1
(the string, not the value of $1
) to the function, executes it and only then does it do the replace. What I want to do is
- Find the occurrence of the pattern
- Replace each occurence with the pattern
- For each replace:
- Pass the capture group to the function
- Use the value of the capture group to get the base64 image
- inject the base64 image into the replacement
Solution 1:
You can use the static Replace
method from the [regex]
class:
[regex]::Replace($text,'-(\d*)-',{param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
Alternatively you can define a regex
object and use the Replace
method of that object:
$re = [regex]'-(\d*)-'
$re.Replace($text, {param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
For better readability you could define the callback function (the scriptblock) in a separate variable and use that in the replacement:
$callback = {
param($match)
'This is the image: ' + (Get-Base64 $match.Groups[1].Value)
}
$re = [regex]'-(\d*)-'
$re.Replace($text, $callback)
Solution 2:
PetSerAl's helpful answer is your only option in Windows PowerShell, as of v5.1.
PowerShell Core v6.1+ now offers a native PowerShell solution via an enhancement to the-replace
operator, which obviates the need to call [regex]::Replace()
:
Just as with [regex]::Replace()
, you can now:
- pass a script block as the
-replace
replacement operand, which must return the replacement string, - except that the match at hand (an instance of type
[System.Text.RegularExpressions.Match]
) is represented as automatic variable$_
, as is customary in PowerShell.
Applied to your case:
$text -replace "-(\d*)-", { "This is the image: $(Get-Base64 $_.Groups[1].Value)" }
A simpler example:
# Increment the number embedded in a string:
PS> '42 years old' -replace '\d+', { [int] $_.Value + 1 }
43 years old