只获取必要内容

Shell提供了两种方式缩小结果集,它们都被归结为过滤。

  • 第一种:尝试指定Cmdlet命令只检索指定的内容,该方式一般称之为左过滤技术
  • 第二种:采用迭代的方法,通过第一个Cmdlet获得所有结果,并使用第二个Cmdlet过滤掉不想要的东西。

考虑到效率,我们应该尽可能提前过滤,即优先使用第一种方式来实现。
例如,使用Get-Service,你可以告诉它你想要的服务名称。
image.png
如果你想让Get-Service只返回正在运行的服务,而不考虑它们的服务名称,该Cmdlet就无法做到这一点,因为它没有提供用于设定该部分信息的相关的参数。

如果你使用微软的活动目录模块,所有以Get-开始的Cmdlets都提供了-filter参数。
image.png

左过滤

“左过滤”意味着尽可能把过滤条件,放置在左侧或靠近命令行的开始部分。越早过滤不需要的对象,就越能减轻其他Cmdlets命令的工作,并且能减少不必要的信息通过网络传输到你的电脑。

当无法通过一个Cmdlet就可以完成你所需的所有过滤时,可以使用**Where-Object**(别名Where或 ? )。当需要检索的时候,可使用它过滤任何类型的对象,并把它传入管道。

为了使用Where-Object,需要学会告诉Shell如何过滤出你想要的信息,这还包括使用Shell的比较操作符。有趣的是,一些左过滤技术中使用了相同的比较操作符,如活动目录模块下以Get-开头的命令的-filter参数。

使用比较操作符

PowerShell使用如下比较操作符。请注意,当比较文本字符串时会忽略大小写。

  • -eq:相等,例如5 -eq 5(返回true)或者”hello” -eq “help”(返回false)。
  • -ne:不等于,例如10 -ne 5(返回true)或者”help” -ne “help”(返回false)。
  • -ge和-le:大于等于,小于等于,例如10 -ge 5(返回true)或者Get-Date -le '2012-12-02'
  • -gt和-lt:大于和小于,例如10 -lt 10(返回false)或者100 -gt 10(返回true)。

对于字符串的比较,如果需要区分大小写,可以使用:-ceq, -cne,-cgt, -clt, -cge, -cle。
也可以使用更加传统的编程语言形式的比较运算符:

  • = 等于
  • <> 不等于
  • <= 小于或等于
  • = 大于或等于

  • 大于

  • < 小于

如果想一次比较多个对象,可以使用布尔运算符-and和-or。通常在每个子表达式两边加上圆括号,使得表达式更容易阅读。

  • (5 -gt 10) -and (10 -gt 100)返回false,因为一个或两个子表达式返回值为false。
  • (5 -gt 10) -or (10 -lt 100)返回true,因为最后一个子表达式返回值为true。

另外,布尔值-not对true和false取反。在处理一个变量或者已经包含true或false的属性时,这可能会有用。
例如,需要测试一个进程是否没有响应,可以这样做:
image.png
Windows PowerShell定义了$False和$True表示false和true的布尔值。另外一种书写方式如下:
image.png
因为Responding通常包含true和false, -not使得false取反变为true。如果进程没有响应,意味着Responding返回false。

  • -not运算符可以简写为感叹号(!)

    使用通配符

    当需要比较文本字符串时,还有其他几个有用的比较运算符。

  • -like:接受作为通配符,如:`”Hello” -like “ll*”`(返回true)。

    • 它的反义运算符为-notlike,它们不区分大小写。
    • 区分大小写可以使用-clike-cnotlike
  • -match用于文本字符串与正则表达式进行比较。
    • -notmatch是个逻辑上的反义词。
    • -cmatch-cnotmatch提供了区分大小写的语法。

about_comparison_operators的帮助文件中,可以找到其他可用的比较运算符。
image.png

过滤对象的管道:Where-Object

一些Cmdlet的-filter参数,可以与活动目录中模块以GET-开头的命令共同使用。也可以与Shell的通用过滤命令Where-Object共同使用。
例如,过滤掉其他信息,只留下正在运行的服务

  1. Get-Service | Where-Object -FilterScript {$_.Status -eq 'Running'}
  2. # 或
  3. Get-Service | Where {$_.Status -eq 'Running'}
  4. # 或
  5. Get-Service | ? {$_.Status -eq 'Running'}

如果阅读上面代码,这会听起来合情合理:“where status equals running”。这就阐述了它的工作原理:

  1. 当你传递多个对象到Where-Object时,它会使用它的过滤器检查每个对象。
  2. 一次只放置一个对象到占位符$_,接着运行比较操作从而查看返回值是true还是false。
  3. 如果是false,该对象就会被管道移除。如果返回true,该对象就会从Where-Object传输到下一个Cmdlet的管道中。
  4. 在上面的示例中,下一个Cmdlet命令是Out-Default,这会是管道的末尾。
  5. 接着开始使用格式化过程,从而显示输出结果。

    占位符$_

    占位符$_是个特殊产物,其只能在PowerShell能查找的特定位置中使用。当它有效时,它一次只包含一个从管道传输到该Cmdlet的对象。
    范例:保留那些-status属性为Running的服务
    image.png
    1)命令是以Get-Service开始,但它却不是第一个运行的命令。而是在圆括号内的Get-Content先运行。
    2)Get-Content通过管道将输出结果(由简单的String对象组成)传递给Where-Object。
  • Where-Object和过滤器处在圆括号内,$_表示从Get-Content管道传输过来的String对象。
  • 只要字符串不是以“dc”结尾的,都会被保留并通过Where-Object输出。

3)Where-Object的输出成为圆括号内的结果,所有不是以“dc”结尾的计算机名称,会被发送到Get-Service的-computername参数中。
4)然后运行Get-Service,并且产生的ServiceController对象将会传输到Where-Object。

Where-Object新式写法

PowerShell v3为Where-Object引入了一个新的“简写”语法。当只比较一次时可以使用该语法,如果需要比较多个子项,请保持使用原来的写法。
image.png
该语法免除了{},并且不需要使用看起来尴尬的占位符$_。但旧语法,仍然需要在复杂的比较中使用它。
image.png

使用迭代命令行模式

此处简单介绍PowerShell迭代命令行模型或者称为PSICLM。PSICLM的核心思想在于你不需要一开始就创建一个大而复杂的命令行,而是从简单的开始。
比方说,要计算正在使用虚拟内存排名前十的进程所占用的虚拟内存总和。如果排名前十的进程中包含PowerShell进程,而又不想在结果中包含PowerShell进程。快速罗列出几个需要的步骤。
1)获取进程列表;
image.png
2)排除PowerShell进程;(实际运用中,优先使用“左过滤”技术)
image.png
3)按照虚拟内存进行排序;
image.png
4)只保存前10个或者最后10个,这取决于排序方式;
image.png
5)把剩下进程的虚拟内存相加。
image.png