powershell 命令周围的括号与没有括号有何不同?

How are parenthesis around a powershell command different than without?

我正在使用 Get-NetIPAddress。我想要的只是没有任何格式或表格或任何东西的实际地址。

如果我使用

(Get-NetIPAddress).IPAddres

我得到了所有端口的地址列表。我只想要一个端口,所以我尝试通过管道传输它,但在 return:

中什么也没给出
(Get-NetIPAddress).IPv4Address | Where-Object InterfaceAlias -eq "MyPortName"

但是如果我这样做:

Get-NetIPAddress.IPv4Address | Where-Object InterfaceAlias -eq "MyPortName"

它说这是一个无效的命令。

如果我使用这个:

Get-NetIPAddress | Where-Object InterfaceAlias -eq "MyPortName" | Where-Object AddressFamily -eq IPv4 | Select-Object IPAddress

我得到:

IPAddress
---------
10.45.22.100

那么当我在 Get-NetIPAddress 周围加上括号时发生了什么,我怎样才能得到特定端口的该死地址号?

通过用 () 括起一个命令,您创建了一个优先顺序,因此 () 内的所有内容都先执行,然后再评估您的其他命令。

此外,没有cmdlet.property

这样的结构

至于第二部分,在您执行 (Get-NetIPAddress).IPv4Address 之后,您可能会得到另一个对象,只需比较输出:

Get-NetIPAddress | Get-Member

(Get-NetIPAddress).IPv4Address | Get-Member

括号的工作方式与它们在数学中的作用相同,它们设置了优先顺序,因此括号内的任何内容都将首先执行。

要从最终命令中仅获取 IP 地址值,请改为执行以下操作:

(Get-NetIPAddress | Where-Object InterfaceAlias -eq "MyPortName" | Where-Object AddressFamily -eq IPv4).IPAddress

这个命令:

(Get-NetIPAddress).IPv4Address

Returns IPv4Address 属性 的值(可能是一个字符串),这就是此命令不起作用的原因:

(Get-NetIPAddress).IPv4Address | Where-Object InterfaceAlias -eq "MyPortName"

当您将包含 IP 地址的字符串对象通过管道传输到 Where-Object cmdlet 中,然后希望过滤该对象中不存在的 InterfaceAlias 属性 .

当您通过 . 符号访问 属性 时,您会得到它的值。当您通过 Select-Object cmdlet 访问 属性 时,您 return 一个对象(与源对象类型相同)被过滤为仅包含单个 属性(除非你使用 -ExpandProperty 开关,这会导致 Select-Object 到 return 定义的 属性 的值而不是对象,就像使用 . 表示法一样).

长话短说,首先进行您需要进行的任何过滤,然后最后访问您想要的 property/properties 结果。

使用您提供的语法:

Get-NetIPAddress | Where-Object InterfaceAlias -eq "MyPortName" | Where-Object AddressFamily -eq IPv4 | Select-Object IPAddress

...仅获取 IP 地址(不带对象符号)可以通过两种方式完成:

Get-NetIPAddress | Where-Object InterfaceAlias -eq "MyPortName" | Where-Object AddressFamily -eq IPv4 | Select-Object -Expand IPAddress

注意 "ExpandProperty" 参数,在上一行缩写为 "Expand" ...或者:

(Get-NetIPAddress | Where-Object InterfaceAlias -eq "MyPortName" | Where-Object AddressFamily -eq IPv4 | Select-Object IPAddress).IPAddress

...我们 return 对象然后引用对象上的 IP 地址 属性。

Get-NetIpAddress 是一个 cmdlet,PowerShell 运行 是它。它输出一个或多个 objects,我的意思是一个 多个名称和数字以及特征全部组合成一个 blob.

Get-NetIpAddress | Select-Object IPv4Address 采用 object(s) 并将它们变成更简单、更小的 objects,只有一个 属性,即 IPv4Address。

就是这样:

IPAddress
---------
10.45.22.100

这是 一个 object 和一个 属性 的渲染。

Get-NetIpAddress | Select-Object -ExpandProperty IPv4Address 采用 objects,仅采用 IPv4Address,并丢弃分组,仅将 IPv4Address 作为字符串保留。

那将输出:

10.45.22.100
10.45.22.101

这些已扩展为字符串,没有列标题。它们已被打开。

这是您很想做的事情,但需要输入大量内容。 $x = Get-NetIpAddress; $x.IPv4Address 是一种仅从 object 中解包 Ipv4Address 的快捷方式,没有其他任何东西。

所以你想做

Get-NetIpAddress.IPv4Address 但是失败了,因为它看起来像是另一个 cmdlet 的名称,而 PowerShell 试图 运行 it 但不能。这只是语法冲突——它可能是一个名字,它可能是一个 属性 查找,而 powershell 选择不同。你需要一些东西(parens)来区分。

(Get-NetIpAddress).IPv4Address 向 shell 明确表示有一个 cmdlet,它 运行 是,然后将结果放入括号中,然后得到 属性 从他们。这消除了名称冲突。但是此时你已经把InterfaceName丢掉了,所以把这个输出推到pipeline是不能让你根据interface name来选择的。

顺着走下去就可以看到

  • 如果你这样做 (Get-NetIPAddress).IPv4Address 输出是字符串,你已经丢弃了来自 cmdlet 的所有其他数据。
  • 如果您想根据接口名称选择一个字符串,则必须在解包 IP 并丢弃接口名称之前这样做。

所以

Get-NetIpAddress | 
    Where-Object { pick the one I want } | 
    Select-Object -ExpandProperty 'the thing I want'