第10-12章10格式化及如何正确使用11过滤和比较12学以致用
第10章 格式化及如何正确使用
10.2 默认格式
你可以在安装PowerShell的路径下找到其中一个名为“.format.ps1xml”的文件。其中进程对象的格式化目录在“DotNetTypes.format.ps1xml”中。注意,不要保存对该文件的任何变更。该文件带有数字签名,即使一个简单的回车或者空格,都会影响签名并阻止PowerShell从中获取信息。
当运行“Get-Process”,在Shell中会发生下面的事情。
(1)Cmdlet把类型为“System.Diagnostics.Process”的对象放入管道。
(2)在管道的末端是一个名称为“Out-Default”的隐藏Cmdlet。
(3)“Out-Default”将对象传输到“Out-Host”。
(4)大部分以Out-开头的Cmdlets不适合用在标准对象中,而主要用于特定格式化指令上。所以当”Out-Host“发现标准对象时,会把它们传递给格式化系统。
(5)格式化系统以其内部格式化的规则检查对象的类型。然后用这些规则产生格式化指令,最终传回”Out-Host“。
(6)一旦”Out-Host“发现已经生成了格式化指令,就会根据该指令生成显示到屏幕上的结果。
在上面5个步骤中,PowerShell依赖于什么格式化规则?其中第一个规则是系统会检查对象类型是否已经被预定义视图处理过。也就是我们在”DotNetType.format.ps1xml“中所见到的:一个针对process对象的预定义视图。
如果没找到对应的视图会发生什么呢?比如运行:
Get-WmiObject Win32_OperatingSystem | Gm
这是格式化系统下一步要做的事情,我们也可以称之为第二个格式化规则:格式化系统会查找是否有人为该对象类型预定义默认显示属性集。这此可以在另一个配置文件”Types.ps1xml“中找到。
如果仍然没有找到,那么下一步将考虑对象全部的属性值。
接下来的分支,即格式化第三个规则——用于确定输出样式。如果格式化系统显示4个或以下的属性,输出结果会以表格形式展现。如果有5个或以上的属性,输出结果会使用列表样式。
10.3 格式化表格
在PowerShell中,有4个用于格式化的Cmdlets。我们将介绍日常使用最多的3种。首先是”Format-Table”,其别名为“Ft”。
该命令有很多参数,我们将演示其中最常用的几个。
- -autosize——通常情况下,PowerShell会根据容器宽度生成表格。
- -property——该参数接收一个逗号分隔符列表,该列表包含期望显示的属性值。
- -groupby——该参数会导致每当指定的属性值发生变化时,生成一个新的列头集合。该参数只有第一次对某个对象的特定属性排序时才能生效。
- -wrap——如果Shell需要把列的信息截断,会在列尾带上省略号(……)以便标识信息被截断。该参数使得Shell可以换行显示剩余信息。
10.4 格式化列表
有时候你所需要展示的信息过多无法适应表格宽度,此时使用列表就很恰当。是时候用上“Format-List”了,注意你可以使用它的别名:Fl。
Get-Service | Fl *
10.5 格式化宽列表
“Format-Wide”(或者别名Fw),用于展示一个宽列表。它仅展示一个属性的值,所以它的“property”参数仅接受一个属性名称,而不是接受列表,并且不接受通配符。
默认情况下,“Format-Wide”会查找对象的“Name”属性。该命令默认输出结果只有两列,但是“-columns”参数可以用于指定输出更多的列。
Get-Process | Format-Wide name -col 4
10.6 创建自定义列与列表条目
“Format-Table”与“Format-List”都能创建自定义列或自定义表条目。
Get-Service | Format-Table @{name='ServiceName';expression={$_.Name},Status,DisplayName}
甚至使用更复杂的数学表达式。
Get-Process |
Format-Table Name,
@{name='VM(MB)';expression={$_.VM/1MB -as [int]}} -autosize
与“Select-Object”不同,它的哈希表仅接受一个Name和Expression作为哈希键。“Format-”命令可以处理用于控制显示的额外的关键字,这些关键字对于“Format-Table”尤其有效。
- FormatString:指定一个格式化代码,使得数据按照指定格式显示,该参数主要用于数值型和日期型数据。可以到MSDN的“Formatting Types”页(
http://msdn.microsoft.com/en-us/library/fbxft59x(v=vs.95).aspx
)中查看用于标准数值与日期格式的格式化代码,以及用于自定义数据值与日期格式的格式化代码。 - Width:指定列宽。
- Alignment:指定列的对齐格式,可以为左对齐或者右对齐。
使用额外的键修改上面的代码,实现同样的输出结果,并更加美观。
Get-Process |
Foramt-Table Name,
@{name='VM(MB)';expression={$_.VM};formatstring='F2';align='right'}
-autosize
现在我们并不需要使用除法,因为PowerShell会以小数并右对齐的形式格式化输出结果。
10.7 输出到文件、打印机或者主机上
另外一种使用管道把格式化指令传递给“Out-File”或“Out-Printer”。
10.8 输出到GridView中
“Out-GridView”提供了另一种形式的输出结果。
get-process | out-gridview
第11章 过滤和比较
11.1 只获取必要的内容
Shell提供了两种方式缩小结果集,它们都被归结为过滤。第一种方式:尝试指定Cmdlet命令只检索指定的内容。第二种方式:采用迭代的方法,通过第一个Cmdlet获得所有结果,并使用第二个Cmdlet过滤掉不想要的东西。
11.2 左过滤
“左过滤”意味着尽可能把过滤条件放置在左侧或靠近命令行的开始部分。越早过滤不需要的对象,就越能减轻其他Cmdlets命令的工作,并且能减少不必要的信息通过网络传输到你的电脑。
当无法通过一个Cmdlet就可以完成你所需的所有过滤时,你可以使用一个叫做Where-Object(它的别名为Where)的核心PowerShell命令。这是一个通用的语法。当需要检索的时候,使用它过滤任何类型的对象,并把它传入管道。
为了使用Where-Object,需要学会告诉Shell如何过滤出你想要的信息,这还包括使用Shell的比较操作符。
11.3 使用比较操作符
PowerShell使用如下比较操作符。请注意,当比较文本字符串时会忽略大小写。
- -eq——相等
- -ne——不等于
- -ge和-le——大于等于,小于等于
- -gt和-lt——大于和小于
对于字符串的比较,如果需要区分大小写,可以使用下面的集合:-ceq,-cne,-cgt,-cge,-clt,-cle。
如果想一次比较多个对象,可以使用布尔运算符-and和-or。通常在每个子表达式两边加上圆括号,使得表达式更容易阅读。 (5 -gt 10) -and (10 -gt 100) #返回false
(5 -gt 10) -or (10 -lt 100) #返回true
另外,布尔运算符-not对true和false取反。在处理一个变量或者已经包含true或false的属性时,这可能会有用。而你想测试相反的条件。
Windows PowerShell定义了$False和$True表示false和true的布尔值。
当你需要比较文本字符串时,还有其他几个有用的比较运算符。
- -like 接受*作为作为通配符。它的反义运算符为 -notlike.它们不区分大小写。区分大小写可以使用-clike和-cnotlike。
- -match 用于文本字符串与正则表达式进行比较。-notmatch是个逻辑上的反义词。并且正如你所想,-cmatch和-cnotmatch提供了区别大小写的语法。
11.4 过滤对象的管道
例如,你是否想过滤掉其他信息,只留下正在运行的服务?
Get-Service | Where-Object -filter { $_.Status -eq 'Running' }
-Filter参数是一个位置参数,这意味着你经常看到很多命令没有显式指定该参数,而它的别名为Where。
Get-Service | Where { $_.Status -eq 'Running' }
11.5 使用迭代命令行模式
我们现在想为你介绍PowerShell迭代命令行模型或者称为PSICLM。PSICLM的核心思想在于你不需要一开始就创建一个大而复杂的命令行,而是从简单的开始。
比方说,你想计算正在使用虚拟内存排名前十的进程所占用的虚拟内存总和。如果排名前十的进程中包含PowerShell进程,而又不想在结果中包含PowerShell进程,快速罗列出几个需要的步骤。
(1)获取进程列表;
(2)排除PowerShell进程;
(3)按照虚拟内存进行排序;
(4)只保存前10个或者最后10个,这取决于我们的排序方式;
(5)把剩下进程的虚拟内存相加。
第4个步骤完全可以使用我们的老朋友:Select-Object。
最终,需要把所有虚拟内存相加。这里就需要寻找新的命令,或许可以通过Get-Commadn或Help加上通配符寻找。可以尝试add关键字,或者sum关键字,甚至是Measure关键字。
Get-Process | Where-Object -filter { $_.Name -notlike 'powershell*' } | Sort VM -descending | Select -first 10
如果使用默认升序排序,你会想加入这最后的命令之前使用-last 10,而不是-first 10。
即使没有使用完全一致的语法,我们也希望你能至少能够找出最后一个Cmdlet的名称。
Get-Process | Where-Object -filter { $_.Name -notlike 'powershell*' } | Sort VM -descending | Select -first 10 | Measure-Object -property VM -sum
第12章 学以致用
12.5 动手实验
Windows8和Windows 2012(或更新版本)包含一个使用文件共享的模块。你的任务是创建一个名称为“LABS”的目录,并共享该目录。为了练习的方便,先假设该目录和共享不存在。先不用管NTFS的权限问题,但请确保共享目录的权限设置为“所有人”拥有读/写权限,并且本地管理员拥有完全控制权。由于共享的主要是文件,你或许希望为文档设置共享缓存。你的脚本还应该展示新建的共享及其权限。
#创建目录
New-Item -Path C:\Labs -Type Directory | Out-Null
#创建共享
$myShare = New-SmbShare -Name Labs -Path C:\Labs\`
-Description "MoL Lab Share" -ChangeAccess Everyone`
-FullAccess Administrators -CachingMode Documents
#获取共享权限
$myShare | Get-SmbShareAccess