PowerShell管道的使用
管道并不是什么新事物,以前的Cmd控制台也有重定向的命令,例如Dir | More可以将结果分屏显示。
传统的Cmd管道是基于文本的,但是Powershell是基于对象。
首先列出当前目录下的目录和文件,然后根据文件名降序排列,再投影文件名,文件大小,文件的修改时间,转换成Html格式,输出到当前目录的ls.html
面向对象的管道
上面的例子属于面向对象的管道,每个命令的末尾可以使用新的命令对上个命令的结果做进一步处理,除非管道是以输出命令结束的。就像Sort-Object一样,对文件的列表进行排序,需要告诉它排序的关键字,按照升序还是降序。ls的返回值为一个数组,数组中的每一个元素都是一个对象,对象的每一个属性都可以作为Sort-Object的排序关键字。但是排序时必须指定一个具体的关键字,因为Powershell所传递的对象可能有很多属性。不像普通的文本,对象的信息都是结构化的,因此也使得Powershell的管道变得更加强大和方便。
转换命令执行的结果为文本
在执行Powershell命令时,解释器会默认在命令的结尾追加一个管道命令,Out-Default,这样可以将原来的对象结果以文本的形式显示在控制台上,但是并没有将结果进行转换,所以可以继续使用其它管道对对象的结果进行操作,但是一旦使用了诸如ConvertTo-Html这样的命令后,就会将结果转换成固定格式的纯文本。
常用的对管道结果进一步处理的命令有:
ConvertTo-Html: 将 Microsoft .NET Framework 对象转换为可在 Web 浏览器中显示的 HTML。
Export-Clixml: 创建对象的基于 XML 的表示形式并将其存储在文件中。
Export-Csv: 将 Microsoft .NET Framework 对象转换为一系列以逗号分隔的、长度可变的 (CSV) 字符串,并将这些字符串保存到一个 CSV 文件中。
ForEach-Object: 针对每一组输入对象执行操作。
Format-List: 将输出的格式设置为属性列表,其中每个属性均各占一行显示。
Format-Table: 将输出的格式设置为表。
Format-Wide: 将对象的格式设置为只能显示每个对象的一个属性的宽表。
Get-Unique: 从排序列表返回唯一项目。
Group-Object: 指定的属性包含相同值的组对象。
Import-Clixml: 导入 CLIXML 文件,并在 Windows PowerShell 中创建相应的对象。
Measure-Object: 计算对象的数字属性以及字符串对象(如文本文件)中的字符数、单词数和行数。
more: 对结果分屏显示。
Out-File: 将输出发送到文件。
Out-Null: 删除输出,不将其发送到控制台。
Out-Printer: 将输出发送到打印机。
Out-String: 将对象作为一列字符串发送到主机。
Select-Object: 选择一个对象或一组对象的指定属性。它还可以从对象的数组中选择唯一对象,也可以从对象数组的开头或末尾选择指定个数的对象。
Sort-Object: 按属性值对象进行排序。
Tee-Object: 将命令输出保存在文件或变量中,并将其显示在控制台中。
Where-Object: 创建控制哪些对象沿着命令管道传递的筛选器。
管道的处理模式
当我们把许多命名组合成一个管道时,可能会感兴趣每一个命令的执行时是顺序执行还是同时执行?通过管道处理结果实际上是实时的。这就是为什么存在两个管道模式:
顺序模式(较慢):在顺序模式中管道中同一时间只执行一条命令,只有当前一条命令的所有执行完毕,才会把所有结果交付给下一条 命令。这种模式速度慢并且耗内存,因为必须需要很多次分配空间存储中间结果。
流模式(较快):流模式会立即执行所有命令,同一时间可能在执行多条命令。前一条命令可能会产生多个结果,但是一旦产生其中一个结果,就会立即交付给下一条命令处理。这样的流模式节省比较节省内存,可能管道的某个任务还在执行,但是已经有部分结果输出了。减少了中间结果的保存。
管道命令的阻塞
可以使用Sort-Object对管道的结果进行排序,但是有时候排序可能导致整个操作系统阻塞,因为排序命令的的执行属于顺序模式,必须得上一条命令的结果全部完成,才能排序。
因此在使用这类命令时,要注意操作对象的大小,和它们需要的内存。例如这条命令:
Dir C: -recurse | Sort-Object
-recurse 选项是递归查询子目录,可想而知系统盘的文件和目录有多大。这条命令一旦运行起来,需要等很长很长的时间,甚至可能导致系统崩溃,得重启电脑。你可以在执行这条命令时,打开任务管理器查看Powershell进程的内存占用在以每秒种几十兆的速率增加。
到底哪些命令可能系统阻塞,要视命令的实现方式以及处理的对象大小决定,例如Sort-object导致阻塞的原因肯定是由于技术实现上采用的是内排序,没有使用外排序。但是象Out-Host -paging 这样的命令属于流出来模式,就一般不会导致系统阻塞。
PowerShell对象转换成文本
怎样将Powershell的对象结果转换成文本并显示在控制台上。Powershell已经内置Out-Default命令追加在管道的命令串的末尾。因此你使用dir 和dir | out-default的结果是相同的。
Out-Default可以将对象转换成可视的文本。事实上Out-Default会首先调用Format-Table,将更多的属性默认隐藏。再调用Out-Host将结果输出在控制台上。因此下面的三组命令执行结果是相同的。
ls
ls | Format-Table | Out-Host
ls | Out-Default
1、显示隐藏的对象属性
要查看对象结果的所有属性,可是使用
ls | Format-Table *
这样因为属性和属性的内容太多可能不会显示完全,可以使用文本换行参数
ls | Format-Table * -Wrap
2、格式化管道结果
首先可是使用下面的命令查看所有以Format打头的命令
Format-Custom: 使用自定义视图来设置输出的格式。
Format-List: 将输出的格式设置为属性列表,其中每个属性均各占一行显示。
Format-Table: 将输出的格式设置为表。
Format-Wide: 将对象的格式设置为只能显示每个对象的一个属性的宽表。
1.显示指定的属性
要显示指定的属性,你首先得知道结果对象中的属性名,例如:
2.使用通配符
例如要查看当前以i打头的进程,并显示进程的名字和其它以”pe”打头,以”64″结尾的进程信息。
3.脚本块作为属性
在Powershell中文件的Length默认以byte作为单位如果你象让它输出时以KB显示,可是考虑下面的方法。
4.修改列标题
使用合成的属性,如果使用脚本块作为标题,看着很不爽。可以使用Lable设置。同样是上面的例子,稍作修改。
5.优化列宽度
因为Powershell的绝大多数输出都是实时的流模式,所以下一条结果的宽度未知,Powershell的结果会默认采用分散对齐,这样可以最大限度利用控制台的宽度,但是可以通过-auto参数对列的宽带进行优化,会将属性值的最大宽带作为每一列的宽度,对比一下吧:
PowerShell排序和分组结果
使用Sort-Object和Group-Object可以对管道结果进行分组。
其实每条命令执行后的结果已经排过序了。例如通过ls 查看文件列表,默认会根据Name属性进行排序(先对文件夹进行排序),但是你可以通过指定属性进行排序例如:
这样默认会根据length进行升序排序,如果要降序排列,可是使用Descending选项。
给对象和哈希表进行排序
如果要完成主要关键字降序,次要关键字升序的排序:
对数据进行分组
如果想查看当前关闭和开启的所有服务,并且通过状态进行分组。可以使用:
再举一例,把当前目录的文件以扩展名进行分组。
使用表达式分组
如果要查看当前目录的文件,根据文件的大小是否大于1KB分组。
如果按照文件名的首字母分组
根据当前应用程序的发布者分组
使用格式化命令分组
Group-Object并不是唯一可以完成分组功能的命令,事实上格式化命令例如Format-Object支持一个GroupBy的参数,也可以完成分组。
PowerShell过滤管道结果
通过管道可以过滤某些对象和对象的属性,这个功能很实用,因为很多时候我们并不是对所有的结果感兴趣,可能只会对某些结果感兴趣。如果要过滤对象可以使用Where-Object;如果要过滤对象的属性,可以使用Select-Object;如果要自定义个性化的过滤效果可以使用ForEach-Object。最后如果想过滤重复的结果,可是使用Get-Uinque。
筛选管道结果中的对象
如果你只对管道结果的特定对象感兴趣,可是使用Where-Object对每个结果进行严格筛选,一旦满足你的标准才会保留,不满足标准的就会自动丢弃。例如你通过Get-service查看运行在机器上的当前服务,但是可能只关心哪些正在运行的服务,这时就可是通过每个服务的属性Status进行过滤。但是前提条件是你得事先知道待处理的对象拥有哪些属性。你可以通过Format-List * ,也可以通过Get-memeber。
知道了对象有哪些属性,要完成上面提到的需求就很容易了。
这里稍微解释一下,Where-Object的参数的是一个布尔表达式,$_代表过滤过程中经过管道的当前结果。另外Where-Object还有一个别名 “?” 更形象。
选择对象的属性
包含在每一个对象中的属性可能有很多,但是并不是所有的属性你都感兴趣,这时可以使用Select-Object 限制对象的属性。接下来的例子演示如果获取机器上匿名帐号的完整信息。
如果你只对用户名、描述,启用感兴趣。
Select-Object也支持通配符。
限制对象的数量
列出最后修改的5个文件
列出占用CPU最大的5个进程
逐个处理所有管道结果
如果想对管道结果进行逐个个性化处理可是使用ForEach-Object
删除重复对象
Get-Unique可以从已排序的对象列表中删除重复对象。Get-Unique会逐个遍历对象,每次遍历时都会与前一个对象进行比较,如果和前一个对象相等就会抛弃当前对象,否则就保留。所以如果对象列表中没有排序,Get-Unique不能完全发挥作用,只能保证相邻对象不重复。