Answers:
这是管道中当前值的变量,$PSItem
在Powershell 3及更高版本中称为该变量。
1,2,3 | %{ write-host $_ }
要么
1,2,3 | %{ write-host $PSItem }
例如,在上面的代码中,%{}
将为数组中的每个值调用该块。的$_
或$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
...好吧,如果您在执行该管道的范围内有一个,它就可以工作$_
。但这与您尝试编写类似内容的通常含义大不相同。
$_
由于某种原因,@ Joey 编写的内容不会遍历所有对象。试试这个吧。 gci | % { $_ | add-member -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar
。我怀疑gci | cmdlet
没有显式的foreach会收集gci结果并将数组传递给cmdlet。但是,数组是一个对象,因此它向数组对象添加了一个属性。该数组没有'name'属性,因此分配给$ _。Bar的值为$ null。底线是$ _广泛用于流水线。不需要%{}来遍历是新的。
gci | % { add-member -InputObject $_ -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar
我认为最简单的方法来考虑此变量,例如C#中的lambda表达式中的输入参数。即$_
类似于C#x
中的x => Console.WriteLine(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
$_
是系统通常在块表达式中创建的变量,该块表达式由与管道(例如Where-Object
和)一起使用的cmdlet引用ForEach-Object
。
但是它也可以用于其他类型的表达式中,例如Select-Object
与表达式属性结合使用。Get-ChildItem | Select-Object @{Name="Name";Expression={$_.Name}}
。在这种情况下$_
表示正在传递的项目,但可以存在多个表达式。
也可以通过自定义参数验证来引用它,其中脚本块用于验证值。在这种情况下,$_
代表从调用中接收到的参数值。
与c#和java最接近的类比是lamda表达式。如果将Powershell分解为基本知识,则所有内容都是脚本块,包括脚本文件a,函数和cmdlet。您可以定义自己的参数,但是在某些情况下,系统会为您创建一个代表要处理/评估的输入项的参数。在这种情况下,自动变量为$_
。