【问题标题】:Why can't I use command substitution instead of piping when using a powershell command such as Get-Member?为什么在使用 Get-Member 等 powershell 命令时不能使用命令替换而不是管道?
【发布时间】:2020-01-16 06:14:36
【问题描述】:

所以我正在尝试使用以下不起作用的命令获取进程的成员列表:

Get-Member $(Get-Process -Name chrome)

产生的错误:

Get-Member : You must specify an object for the Get-Member cmdlet.

但是,这是可行的:

Get-Process -Name chrome | Get-Member

所以命令替换不会生成对象类型输出?有人可以帮我理解其中的区别吗?

谢谢

【问题讨论】:

  • 很多参数不处理数组,除了通过管道。使用进程块编写脚本更容易。

标签: powershell syntax parameter-passing


【解决方案1】:

为了将输入传递给Get-Member通过参数(而不是通过管道),您必须明确使用-InputObject 参数:

Get-Member -InputObject (Get-Process -Name chrome)

还要注意 (...) 在这里就足够了 - 不需要 $(...)[1]

然而,一个重要的警告是,如果Get-Process 返回多个 进程,它们将被收集到一个数组 中,然后Get-Member 将报告数组的属性,而不是它的元素

只有通过管道,输入才被单独考虑,这在Get-Member的情况下意味着distinct集报告了输入类型,Get-Process 输入根据定义只有一个不同类型,[System.Diagnostics.Process]

虽然在 Get-Member 的情况下,pipelineargument 输入之间的区别很有帮助 - 它允许您检查 collection 的属性如果您使用
-InputObject 参数,则类型自己
- 在大多数情况下,它无用并且会造成混淆
,因为大多数 cmdlet 仅在集合的单个元素 - 如果您通过 -InputObject 传递集合,这通常不起作用;见this GitHub issue


至于你尝试了什么

如果您不将-InputObjectGet-Member 显式结合使用,您的参数将绑定到-Name 参数(用于查找特定类型成员),这意味着Get-Member 缺少输入对象,这就是它抱怨的原因。

(请注意,如何将位置参数绑定到其参数取决于每个 cmdlet,并且 cmdlet 甚至可以选择根本不支持位置参数。)

通过查看Get-Member -?Get-Command -Syntax Get-Member 的语法图,您可以知道Get-Member 将第一个位置参数绑定到-Name,如Get-Member -?Get-Command -Syntax Get-Member

PS> Get-Command -Syntax Get-Member

Get-Member [[-Name] <String[]>] [-InputObject <psobject>] ...

参数name -Name 周围的[...] 表示指定参数name 是可选的,即给出的第一个positional 参数绑定到它。
相比之下,-InputObject 参数名没有包含在[...] 中,表示它不能进行位置绑定,要绑定到它的参数必须在参数名之前。 p>

-InputObject 参数 - 通常也是在这种情况下 - 也受 管道输入 的约束,并且通过管道提供输入更为典型(并且通常是唯一有意义的方式,如上所述)。

注意语法图指出哪些参数(可以有多个)接受管道输入;改变这是this GitHub feature request的主题。

有关如何阅读 PowerShell 语法图的更多信息,请参阅about_Command_Syntax


[1] PowerShell 没有 Bash 样式的命令替换。您可以将命令和表达式用作参数,只需将它们包含在(...) 中,然后按原样使用生成的对象(不执行 Bash 样式的 shell 扩展);仅当您想传递 多个 语句的输出,或在 expandable strings ("...") 内部或通过管道发送复合语句的输出(例如,foreach (...) { ... })时,您才需要 $(...), the so-called subexpression operator

【讨论】:

  • 那么如果我提供-Name 参数,例如Get-Member $(Get-Process -Name chrome).name,为什么会出现同样的错误?如果我包含它,'$(Get-Process -Name chrome).name' 将不再绑定到 -Name 参数吗?
  • @Mike:您仍然为Get-Member 提供only -Name 参数 - 无论您是否直接 这样做通过.Name 或通过强制间接 对字符串[array] 的字符串[array] 是无关紧要的。由于 -Name 单独的参数对于 Get-Member 是不够的,它抱怨缺少输入。另外,请记住在这种情况下使用(...),而不是$(...)
  • @Mike:我添加了有关参数绑定和语法图的更多信息。
猜你喜欢
  • 2017-01-02
  • 2021-12-31
  • 2018-02-18
  • 1970-01-01
  • 2016-03-25
相关资源
最近更新 更多