【问题标题】:Use a function in Powershell replace在 Powershell 中使用函数替换
【发布时间】:2016-04-24 14:17:36
【问题描述】:

我正在尝试替换 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 powershell


    【解决方案1】:

    您可以使用[regex] 类中的静态Replace 方法:

    [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)"})
    

    为了更好的可读性,您可以在单独的变量中定义回调函数(脚本块)并在替换中使用它:

    $callback = {
      param($match)
      'This is the image: ' + (Get-Base64 $match.Groups[1].Value)
    }
    
    $re = [regex]'-(\d*)-'
    $re.Replace($text, $callback)
    

    【讨论】:

    • 对于那些希望了解其推导的人来说,它使用了 Replace 方法 (Regex.Replace Method (String, MatchEvaluator)) 的签名,通过允许对匹配的参数进行计算,为正则表达式增加了更多功能。巧妙的是——直到我看到这个答案我才意识到——PowerShell 脚本块显然与 MatchEvaluator 参数兼容!
    【解决方案2】:

    PetSerAl's helpful answer 是您在 Windows PowerShell 中的唯一选择,从 v5.1 开始。

    PowerShell Core v6.1+ 现在通过对
    -replace 运算符
    的增强提供本机 PowerShell 解决方案,无需调用 @987654323 @:

    就像[regex]::Replace() 一样,您现在可以:

    • 传递一个脚本块作为-replace替换操作数,它必须返回替换字符串,
    • 除了手头的匹配项([System.Text.RegularExpressions.Match] 类型的实例)表示为自动变量 $_,这是 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
    

    【讨论】:

    • 这应该是公认的答案
    【解决方案3】:

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

    $text = "the image is -12345-"
    function Get-Base64($path) { 
      [convert]::ToBase64String( (get-content $path -asbytestream) ) }  # ps 6 ver
    if (! (test-path 12345)) { echo hi > 12345 }
    $text -match '-(\d*)-'
    $text -replace '-(\d*)-', "$(Get-Base64 $matches.1)"
    
    the image is aGkNCg==
    

    或者进一步分解:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 2020-04-06
      相关资源
      最近更新 更多