Regex 在Powershell replace中使用函数

Regex 在Powershell replace中使用函数,regex,powershell,Regex,Powershell,我正在尝试替换Powershell中字符串的一部分。但是,替换字符串不是硬编码的,它是根据函数计算的: $text = "the image is -12345-" $text = $text -replace "-(\d*)-", 'This is the image: $1' Write-Host $text 这给了我正确的结果: “这是图像:12345” 现在,我想包括base64编码的图像。我可以从id中读取图像。我希望以下操作可以正常工作,但实际情况并非如此: function Ge

我正在尝试替换Powershell中字符串的一部分。但是,替换字符串不是硬编码的,它是根据函数计算的:

$text = "the image is -12345-"
$text = $text -replace "-(\d*)-", 'This is the image: $1'
Write-Host $text
这给了我正确的结果: “这是图像:12345”

现在,我想包括base64编码的图像。我可以从id中读取图像。我希望以下操作可以正常工作,但实际情况并非如此:

function Get-Base64($path)
{
    [convert]::ToBase64String((get-content $path -encoding byte))
}
$text -replace "-(\d*)-", "This is the image: $(Get-Base64 '$1')"
它不起作用的原因是,它首先将
$1
(字符串,而不是
$1
的值)传递给函数,执行它,然后才执行替换。我想做的是

  • 找到模式的出现点
  • 用模式替换每次出现的情况
  • 对于每次更换:
  • 将捕获组传递给函数
  • 使用捕获组的值获取base64映像
  • 将base64映像注入替换映像
您可以使用
[regex]
类中的静态方法:

[regex]::Replace($text,'-(\d*)-',{param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
或者,您可以定义一个
regex
对象,并使用该对象的
Replace
方法:

$re = [regex]'-(\d*)-'
$re.Replace($text, {param($match) "This is the image: $(Get-Base64 $match.Groups[1].Value)"})
为了更好的可读性,您可以在单独的变量中定义回调函数(scriptblock),并在替换中使用它:

$callback = {
  param($match)
  'This is the image: ' + (Get-Base64 $match.Groups[1].Value)
}

$re = [regex]'-(\d*)-'
$re.Replace($text, $callback)
是自v5.1起Windows PowerShell中的唯一选项

PowerShell Core v6.1+现在通过对
-replace
操作符
,无需调用
[regex]::replace()

正如使用
[regex]::Replace()
一样,您现在可以:

  • 将脚本块作为
    -replace
    替换操作数传递,该操作数必须返回替换字符串
  • 除了手边的匹配项(类型为
    [System.Text.RegularExpressions.match]
    的实例)表示为自动变量
    $\uu
    ,这在PowerShell中很常见
适用于您的情况:

$text -replace "-(\d*)-", { "This is the image: $(Get-Base64 $_.Groups[1].Value)" }
一个简单的例子:

# Increment the number embedded in a string:
PS> '42 years old' -replace '\d+', { [int] $_.Value + 1 }
43 years old

还有一种方法。使用-match运算符,然后引用$matches。请注意,$matches不使用-match操作符左侧的数组进行设置$matches.1是由()组成的第一个分组

或者更进一步地打破它:

$text -match '-(\d*)-'
$result = Get-Base64 $matches.1
$text -replace '-(\d*)-', $result

对于那些希望理解其推导的人来说,它使用了
Replace
方法()的符号,通过允许对匹配的参数进行计算,为正则表达式增加了更多的功能。最妙的是——直到看到这个答案我才意识到——PowerShell脚本块显然与MatchEvaluator参数兼容!
$text -match '-(\d*)-'
$result = Get-Base64 $matches.1
$text -replace '-(\d*)-', $result