微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 Powershell 的 Set-Content -Value 参数不能正确读取管道变量

如何解决为什么 Powershell 的 Set-Content -Value 参数不能正确读取管道变量

所以我试图获取一堆文件内容来替换标题字符串:

$replaces = dir | select Name,@{n='content';e={(get-content $_) -replace "header-foo","header-bar"}}

然后给我一个列表:

Name       Content
----       ----------
a.txt      header-foo blah blah
b.txt      header-foo blah blah blah
c.txt      header-foo blah

然后我想像这样将这个值传递给 set-content -value:

$replaces | set-content -Path {"alt/" + $_.Name} -Value {$_.content}

现在只有我的所有文件都有内容 $_.content。我也试过 -Value ($_.content) 但这也没有做正确的事情。

只有当我使用 foreach 时它才起作用:

$replaces | foreach { set-content -Path ("alt/" + $_.Name) -Value $_.content }

为什么会这样?为什么没有 foreach 就不能正常工作?

解决方法

您正在尝试使用 delay-bind script block ({ ... }) 来动态确定 Set-Content-Value 参数的参数,基于每个管道输入对象。

但是,delay-bind 脚本块不能与 -Value 一起使用,因为该参数的类型是 [object[]] (System.Object[])(请参阅 {{1} });同样的限制适用于 Get-Help -Parameter Value Set-Content 类型的参数。

要解决此限制,您确实需要一个类似循环的构造,以便为每个预期的 [scriptblock] 参数调用一次 Set-Content ,就像您对 ForEach-Object(其内置别名为 -Value)cmdlet 所做的那样。


foreach[object] 参数(及其数组变体)不能作为延迟绑定脚本块工作的原因是,作为脚本块传递给这些参数会立即绑定它,如-is,因为参数类型匹配参数类型。

对于任何其他参数类型 - 假设参数被指定为接受管道输入 - PowerShell 推断脚本块参数是延迟绑定脚本块,并为每个管道输入对象评估脚本块 em>,正如预期的那样,然后脚本块必须确保其输出的类型与目标参数匹配。

,

您的问题是在“get-content $”中,您必须使用 get-content $.Name

但是你应该像这样修改你的脚本:

  1. 使用 Get-childItem(标准 powershell)
  2. 使用 -file 只获取文件而不是目录
  3. 使用FullName,必要时可以使用recurse
  4. 使用 .Replace 而不是 -replace 运算符(在这种情况下不起作用)

-替换使用正则表达式:detail here

$replaces = Get-ChildItem -file | select FullName,@{n='content';e={(get-content $_.FullName).Replace('header-foo','header-bar')}}
$replaces | %{set-content -Path $_.FullName -Value $_.content}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。