[英]Why does Powershell's Set-Content -Value argument not read Pipeline Variable correctly
So I'm trying to get the contents of a bunch of files to replace the header string:所以我试图获取一堆文件的内容来替换 header 字符串:
$replaces = dir | select Name, @{n='content';e={(get-content $_) -replace "header-foo","header-bar"}}
That then gives me a list of:然后给了我一个列表:
Name Content
---- ----------
a.txt header-foo blah blah
b.txt header-foo blah blah blah
c.txt header-foo blah
Then I want to pass the value of this to set-content -value like so:然后我想将 this 的值传递给 set-content -value,如下所示:
$replaces | set-content -Path {"alt/" + $_.Name} -Value {$_.content}
Only all of my files have the content $_.content
now.现在只有我所有的文件都有内容$_.content
。 I also tried -Value ($_.content)
but that doesn't do the right thing either.我也试过-Value ($_.content)
但这也不是正确的事情。
It's only when I use a foreach does it work:只有当我使用 foreach 时它才会起作用:
$replaces | foreach { set-content -Path ("alt/" + $_.Name) -Value $_.content }
Why is this the case?为什么会这样? Why does it not work correctly without the foreach
?为什么没有foreach
就不能正常工作?
You're trying to use a delay-bind script block ( {... }
) in order to dynamically determine the argument for Set-Content
's -Value
parameter, based on each pipeline input object.您正在尝试使用延迟绑定脚本块( {... }
) ,以便根据每个管道输入 object 动态确定Set-Content
的-Value
参数的参数。
However, delay-bind script blocks cannot be used with -Value
, because that parameter's type is [object[]]
( System.Object[]
) (see Get-Help -Parameter Value Set-Content
);但是,延迟绑定脚本块不能与-Value
一起使用,因为该参数的类型是[object[]]
( System.Object[]
) (请参阅Get-Help -Parameter Value Set-Content
); the same limitation applies to [scriptblock]
-typed parameters.同样的限制适用于[scriptblock]
类型的参数。
To work around this limitation, you do need a loop-like construct in order to invoke Set-Content
once for every intended -Value
argument , as you have done with the ForEach-Object
(whose built-in alias is foreach
) cmdlet.要解决此限制,您确实需要一个类似循环的构造,以便为每个预期的-Value
参数调用一次Set-Content
,就像您使用ForEach-Object
(其内置别名是foreach
)cmdlet 所做的那样。
The reason that [object]
and [scriptblock]
parameters (and their array variants) do not work as delay-bind script blocks is that passing as script block to such parameters binds it instantly, as-is , because the argument type matches the parameter type. [object]
和[scriptblock]
参数(及其数组变体)不能作为延迟绑定脚本块工作的原因是,作为脚本块传递给此类参数会立即将其绑定,因为参数类型与参数匹配类型。
With any other parameter type - assuming that the parameter is designated as accepting pipeline input - PowerShell infers that a script-block argument is a delay-bind script block and evaluates the script block for each pipeline input object , as intended, and the script block must then ensure that its output is of a type that matches the target parameter.对于任何其他参数类型 - 假设参数被指定为接受管道输入 - PowerShell 推断脚本块参数是延迟绑定脚本块并评估每个管道输入 object的脚本块,如预期的那样,以及脚本块然后必须确保其 output 是与目标参数匹配的类型。
You problem is in "get-content $ " you must use get-content $ .Name你的问题是在 "get-content $ " 你必须使用 get-content $ .Name
But you should modify you script like this:但是你应该像这样修改你的脚本:
-replace use regular expression: detail here -replace 使用正则表达式: 这里有详细信息
$replaces = Get-ChildItem -file | select FullName, @{n='content';e={(get-content $_.FullName).Replace('header-foo', 'header-bar')}}
$replaces | %{set-content -Path $_.FullName -Value $_.content}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.