在PowerShell中,$_的真正含义是什么?

6

可能是重复问题:
在PowerShell中,$_代表什么意思?

我已经看到了其他人关于同一主题的问题和答案, 但对我来说它没有回答我的问题。

我知道如何使用Select-Object、Where-Object、ForEach-Object等,并传递一个脚本块,例如:

dir | ForEach-Object { $_.Name }

该函数返回当前目录中所有文件名的数组。
这类似于C#的Select扩展方法:
Dir.Select(x => x.Name)

然而,上述的C#很容易理解,因为我们向Select方法传递了一个函数,该函数然后对列表中的每个元素执行它。
然而,在PowerShell中的等效代码:
dir | ForEach-Object { param($x) $x.Name }

不返回任何内容。但是

& { param($x) $x.Name } (dir)[0]

正常工作。

有人能否向一个熟悉C#但不熟悉脚本编程的人解释一下$_的奥妙?它是一个特殊的关键字吗?它只能用于传递给cmdlet的脚本块中吗?如何在不将其管道传递到ForEach-Object(或任何其他cmdlet)的情况下调用它?例如:

& { $_.Name } (dir)[0]

?


2
这不是另一个问题的完全重复(我在这个问题的第一行就说了)。另一个问题或多或少地询问如何使用它,而不是它的意思。你可以看出这不是重复的,因为被接受的答案是不同的。zdan的答案表明直接将某些内容传输到过滤器是可能的,而JaredPar的答案则显示将某些内容传输到ForEach-Object。两者之间的区别在于直接调用过滤器还是将过滤器传递给另一个过滤器,然后执行它。 - Tahir Hassan
2个回答

9
$_变量只在管道上下文中创建,即从一个命令传递输出对象到另一个命令的“输入”。对于管道过滤器(类似于函数),PowerShell会自动使用当前的对象填充$_变量。现在我说“当前”是很重要的,因为需要注意的是当多个对象通过管道传递时,您的过程脚本块将针对每个对象执行一次。
您可以将管道对象重命名为您的输入参数之一,但必须告诉PowerShell您正在这样做。例如:
# C:\> filter get-name-filt {Param([parameter(ValueFromPipeline=$true)]$x) $x.name}
# C:\> (dir)[0] | get-name-filt

在命令行上使用这种方式并不是特别方便,因此需要使用 $_ 自动变量。


感谢这个答案完美地解释了什么是 $_。 - Tahir Hassan

4
$_ 是当前的管道项。
例如:
 dir | ForEach-Object { $_.Name }

意思:

  1. 运行dir命令
  2. 将输出传递给下一个管道命令
  3. ForEach-Object使用dir的输出作为名为$ _的变量

由于dir的输出具有属性.name,因此流水线化的$_也将具有相同的属性。 这只是一种通过管道传递数据的方法。


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