在PowerShell的ForEach-Object循环中,$_的范围是什么?

3

这是我正在尝试编写的脚本的简化版本:

$i = 0
Get-ChildItem -Filter *.bat|
ForEach-Object {
    Write-Host $_.Name
    switch ($i) {
        0 { Write-Host $_.Name}
        1 { Write-Host $_.Name }
        2 { Write-Host $_.Name }
        Default {Write-Host "nothing here"}
    }
}

第一条Write-Host命令按预期工作,但一旦进入switch语句,Write-Host就不打印任何东西,这让我感到困惑。我认为问题与$_的作用域有关,但我不知道。我是一个完全的Powershell菜鸟。难道switch语句不是在foreach循环内部吗?所以作用域不应该是个问题吗?

如果我这样做,那么一切都像我预期的那样工作,文件名从switch语句内部和外部都被打印出来:

$i = 0
Get-ChildItem -Filter *.bat |
ForEach-Object {
    Write-Host $_.Name
    $temp = $_.Name
    switch ($i) {
        0 { Write-Host $temp }
        1 { Write-Host $temp }
        2 { Write-Host $temp }
        Default {Write-Host "nothing here"}
    }
}

有人能解释一下这里发生了什么吗?


除了答案中提供的信息外,我还推荐您关注 Microsoft Learn on Scopes in Powershell - Jeff Zeitlin
2个回答

3

如下所述:

about_Switch

问题在于,自动变量 $_ 包含传递到 switch 语句的表达式的值。这意味着它不包含进入 switch 语句之前的相同值。

此外,如果您想了解有关 $_ 的更多信息,您还可以参考本文:

PowerShell中的 $_ 是什么意思

祝你好运 :)


2

$_在你的switch语句中得到了不同的值 - 它实际上获取了$i的值,因此它是一个Int32类型,并且没有Name属性。当你给$temp赋值并在switch语句中使用它时,它可以工作,因为你将想要的(字符串)值分配给了一个新变量。

如果你在switch之后再次使用$_,你仍然能够像以前一样访问所有属性。

通过使用下面的代码,你可以看到在不同的范围/管道中使用$_所采取的类型。

Get-ChildItem -Filter *.bat |
ForEach-Object {
    Write-Host $_.gettype()
    switch ($i) {
        Default {
          Write-Host $_.gettype()
        }
    }
}

好的,$_ 是管道变量,因为 switch 语句以 $i 作为输入,所以 $i 成为新的管道变量,直到 switch 结束? - robynChill
是的,那是正确的。 - arco444
我发现我的错误在于没有考虑到 $_ 可能有其他用途。文档中只说使用 $_ 变量来访问当前对象。如果它提到了 $_ 可能被其他东西覆盖,对像我这样的自学业余爱好者会很有帮助。所以这并不是作用域问题。 - robynChill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接