我在 PowerShell 中看到了很多以下内容,但它到底做了什么?
$_
这是管道中当前值的变量,在 Powershell 3 和更高版本中称为 $PSItem
。
1,2,3 | %{ write-host $_ }
或者
1,2,3 | %{ write-host $PSItem }
例如,在上面的代码中,数组中的每个值都会调用 %{}
块。 $_
或 $PSItem
变量将包含当前值。
我认为考虑这个变量的最简单方法是 C# 中 lambda 表达式中的输入参数。即$_
类似于C# 中x => Console.WriteLine(x)
匿名函数中的x
。考虑以下示例:
电源外壳:
1,2,3 | ForEach-Object {Write-Host $_}
印刷:
1
2
3
或者
1,2,3 | Where-Object {$_ -gt 1}
印刷:
2
3
并将其与使用 LINQ 的 C# 语法进行比较:
var list = new List<int> { 1, 2, 3 };
list.ForEach( _ => Console.WriteLine( _ ));
印刷:
1
2
3
或者
list.Where( _ => _ > 1)
.ToList()
.ForEach(s => Console.WriteLine(s));
印刷:
2
3
根据 this 网站,它是对 this
的引用,主要是在循环中。
$_(美元下划线)'THIS' 标记。通常指的是 foreach 循环中的项目。任务:打印集合中的所有项目。解决方案。 ... | foreach { 写主机 $_ }
this
是 $_
变量的一个相当混乱的术语。在 OOP 中,它通常指的是类,而不是变量。
$_ 是自动变量 $PSItem(在 PowerShell V3.0 中引入;Usage information found here)的别名,它代表管道中的当前项目。
自动变量的 PowerShell (v6.0) 在线文档是 here。
$_
是由系统创建的变量,通常位于块表达式中,这些表达式由与管道一起使用的 cmdlet 引用,例如 Where-Object
和 ForEach-Object
。
但它也可以用于其他类型的表达式,例如将 Select-Object
与表达式属性结合使用。 Get-ChildItem | Select-Object @{Name="Name";Expression={$_.Name}}
。在这种情况下,$_
表示正在通过管道传输的项目,但可以存在多个表达式。
它也可以被自定义参数验证引用,其中脚本块用于验证值。在这种情况下,$_
表示从调用接收到的参数值。
与 c# 和 java 最接近的类比是 lamda 表达式。如果您将 powershell 分解为基础,那么一切都是一个脚本块,包括脚本文件 a、函数和 cmdlet。您可以定义自己的参数,但在某些情况下,系统会为您创建一个参数,代表要处理/评估的输入项。在这些情况下,自动变量是 $_
。
$_ 是一个变量,它迭代从前一个 | 传递的每个对象/元素。 (管道)。
$_ 是一个 $PSItem,它本质上是一个从另一个命令传递过来的对象。例如,在我的工作站上运行 Get-Volume 会返回 PSItem 行或对象
get-volume | select driveLetter,DriveType
driveLetter DriveType
----------- ---------
D Fixed
Fixed
C Fixed
A Removable
Driveletter 和 DriveType 是属性 现在,您可以在使用 $_.(propertyName) 管道输出时使用这些项目属性。 (还要记住 % 是 Foreach-Object 的别名)例如
$vol = get-volume | select driveLetter,DriveType
$vol | Foreach-Object {
if($_.DriveType -eq "Fixed") {
"$($_.driveLetter) is $($_.driveType)"}
else{
"$($_.driveLetter) is $($_.driveType)"
}
}
在 Powershell 7 中使用 Terinary,我可以在使用 Piped PSItem 的属性时缩短逻辑
ForEach-Object
或Where-Object
中很好地使用它,但您不能在Get-Foo|Add-Member NoteProperty Bar ($_.SomeProperty)
之类的地方使用它 - 涉及管道,但没有脚本块,因此没有$_
。 (话虽这么说,PowerShell 帮助还提到了$_
的管道。令人困惑。)Get-Foo | Add-Member -Type NoteProperty -Name Bar -Value $_.SomeProperty
Get-ChildItem | Add-Member -Type NoteProperty -Name Bar -Value $_.Name -PassThru | Select Bar
...好吧,如果你在你的范围内有一个$_
,它可以工作'重新执行该管道。但这与您尝试编写类似内容时通常的意思大不相同。$_
在您所写的内容中,出于某种原因,并未遍历所有对象。试试这个。gci | % { $_ | add-member -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar
。我怀疑没有显式 foreach 的gci | cmdlet
正在收集 gci 结果并将数组传递给 cmdlet。但是,数组是一个对象,所以它为数组对象添加了一个属性。该数组没有“名称”属性,因此分配给 $_.Bar 的值为 $null。底线是 $_ 在流水线中被广泛使用。不需要 %{} 循环是新的。gci | % { add-member -InputObject $_ -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar