首页 > 解决方案 > 如何在 Powershell 管道中引用前一个“管道”的输出?

问题描述

我编写了这段代码来获取一些(相对)文件路径:

function Get-ExecutingScriptDirectory() {
    return Split-Path $script:MyInvocation.MyCommand.Path  # returns this script's directory
}

$some_file_path = Get-ExecutingScriptDirectory | Join-Path -Path $_ -ChildPath "foo.json"

这引发了错误:

Join-Path : Cannot bind argument to parameter 'Path' because it is null.
+ $some_file_path  = Get-ExecutingScriptDirectory | Join-Path -Path $_ -ChildPath "fo ...
+                                                     ~~
    + CategoryInfo          : InvalidData: (:) [Join-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCommand

这向我表明,Get-ExecutingScriptDirectory当我像这样编写脚本时,输出为 null - 但它不是 - 很好:

$this_directory = Get-ExecutingScriptDirectory
$some_file_path = Join-Path -Path $this_directory -ChildPath "foo.json"

所以问题是它$_是空的。我希望$_引用前一个管道的标准输出。MSDN 文档也提出了这一点,但它似乎立即自相矛盾:

$_ 包含管道对象中的当前对象。您可以在对每个对象或管道中的选定对象执行操作的命令中使用此变量。

在我的代码上下文中,$_似乎符合“管道对象中的当前对象”的条件 - 但我没有将它与对每个对象或管道中选定对象执行操作的命令一起使用。

$$看起来很有希望,$^但是 MSDN 文档在这里只说了一些关于词法标记的模糊的东西。上的文档$PSItem同样简洁。

我真正想做的是创建一个大管道:

$some_file_path = Get-ExecutingScriptDirectory | Join-Path -Path {{PREVIOUS STDOUT}} -ChildPath "foo.json" | Get-Content {{PREVIOUS STDOUT}} | Convert-FromJson {{PREVIOUS STDOUT}} | {{PREVIOUS STDOUT}}.data

我想知道我在概念和技术层面上哪里出错了。

标签: powershellvisual-studio-codepowershell-5.0

解决方案


这是一个简单的例子。在文档中搜索“接受管道输入”。使用带有 get-content 的 -path 参数的脚本块有点高级。大多数人使用 foreach-object 代替。它之所以有效,是因为 -path 接受管道输入,但只能通过属性名称。join-path 的 -path 参数可以按值在管道上,因此更容易。一旦你理解它,这将派上用场。也许有时尝试一下会更容易。

echo '"hi"' > foo.json

'.\' | Join-Path -ChildPath foo.json | Get-Content -Path { $_ } | ConvertFrom-Json

hi

或者使用 foreach,在这种情况下是 foreach-object 的缩写。但 $_ 必须始终位于花括号内。

'.\' | Join-Path -ChildPath foo.json | foreach { Get-Content $_ } | ConvertFrom-Json

推荐阅读