欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《Learn Windows PowerShell in a Month of Lunches Third Edition》读书笔记——CHAPTER 9 The pipeline, deeper

程序员文章站 2022-07-14 21:05:53
...

9.2 How PowerShell passes data down the pipeline

对于形如 PS C:\> CommandA | CommandB 的命令,PowerShell必须指出如何将第一个命令的输出作为第二个命令的输入,即得指出 CommandB 的哪个参数来接受 CommandA 的输出。这个指出的过程叫做 pipeline parameter binding 。PowerShell有两种方法来达到这个目的,其首先尝试的方法叫 ByValue ,其次会尝试 ByPropertyName

9.3 Plan A: pipeline input ByValue

With this method of pipeline parameter binding, PowerShell looks at the type of object produced by Command A and tries to see whether any parameter of Command B can accept that type of object from the pipeline.

在此方法中,PowerShell查看Command A产生的对象,然后尝试匹配到Command B的某个可以接受该对象的参数上。

我们可以人为的模拟这个过程,以 Get-Content .\computers.txt | Get-Service 为例:
computer.txt内容如下:

SERVER2
WIN8
CLIENT17
DONJONES1D96
  1. 首先将Command A的输出pipe到 Get-Member ,查看Command A输出的对象类型
  2. 查看Command B完整的帮助查找是否有某一参数接受该类型的数据,如 Help Get-Service -full
    《Learn Windows PowerShell in a Month of Lunches Third Edition》读书笔记——CHAPTER 9 The pipeline, deeper

如果使用 ByValue 无法找到匹配的参数,那么PowerShell会使用 ByPropertyName 来查找。比如例子 get-service -name s* | stop-process 就不能使用 ByValue

9.4 Plan B: pipeline input ByPropertyName

so let’s be clear on how simple the shell is being: It’s looking for property names that match parameter names. That’s it. Because the property Name is spelled the same as the parameter -Name, the shell tries to connect the two.

对于这种方法,PowerShell所做的就是寻找和Command B参数名字 匹配的 由Command A输出的对象的属性的名字。

我们也可以人为的模拟该过程,以 get-service -name s* | stop-process 为例:
1. 首先将Command A的输出pipe到 Get-Member
2. 查看Commad B的语法
《Learn Windows PowerShell in a Month of Lunches Third Edition》读书笔记——CHAPTER 9 The pipeline, deeper

找到相同的之后,PowerShell还要查看Command B的该参数是否接受pipeline输入 ByPropertyName

不过,不像 ByValue 只涉及到一个参数。在每个参数都允许受pipeline输入 ByPropertyName 的时候,ByPropertyName 会连接每个匹配的属性和参数。

9.6 Parenthetical command

有些命令的参数是不支持pipeline input的,比如 Get-WmiObject-ComputerName 参数。所以说 get-content .\computers.txt | get-wmiobject -class win32_bios 是不行的。想要从文件中读取内容到该参数中,就要使用圆括号来改变命令的运算顺序,如 Get-WmiObject -class Win32_BIOS -ComputerName (Get-Content .\computers.txt)

9.7 Extracting the value from a single property

当使用圆括号的时候,得保证参数允许接受的值的类型和圆括号内计算出来的类型相同,否则会执行失败。如 Get-Service -computerName (Get-ADComputer -filter * -searchBase "ou=domain controllers,dc=company,dc=pri) ,因为 -computerName 参数希望接受 String 类型的值,而 Get-ADComputer -filter * -searchBase "ou=domain controllers,dc=company,dc=pri 得到的对象的类型是 ADComputer ,所以该命令不会执行成功。

想要该句执行成功,那么就可以尝试从对象的单个属性中抽取值。比如对象 ADComputer 有一个叫做 Name 的属性可以满足 -ComputerName 参数需要的值,我们要得就是从该属性中取出 Name 属性的值。

要达到上述抽取的目的,我们可以使用cmdlet Select-Object 。该cmdlet有一个 -expandProperty 参数可以接受属性的名字。如 Get-ADComputer -filter * -searchbase "ou=domain controllers,dc=company,dc=pri" | Select-Object -expand name

至于其参数 -expandProperty-Property 的区别是:

With Select -Property, you’re deciding what boxes you want, but you still have boxes.
With Select -ExpandProperty, you’re extracting the contents of the box and getting rid of the box entirely. You’re left with the contents.
个人的理解是, -Property 会保留原来对象的类型,也就是还是个对象。但是 -ExpandProperty 就把原来的类型便成了字符串。