PowerShell 技能连载 - 格式化数字(第 2 部分)
在前一个技能中我们介绍了 Get-DisplayFileSize
函数,它可以自动将字节数转换成容易阅读的带单位的数字,例如 “KB” 和 “MB”。
使用 Select-Object
指令,您可以创建一个带有易读的文件尺寸的文件夹列表:
1 | $Length = @{ |
请注意计算属性 Length
仍然可以用于排序。它仍是字节数据,只是显示的方式改变了。
在前一个技能中我们介绍了 Get-DisplayFileSize
函数,它可以自动将字节数转换成容易阅读的带单位的数字,例如 “KB” 和 “MB”。
使用 Select-Object
指令,您可以创建一个带有易读的文件尺寸的文件夹列表:
1 | $Length = @{ |
请注意计算属性 Length
仍然可以用于排序。它仍是字节数据,只是显示的方式改变了。
以下 Get-DisplayFileSize
函数接受任何字节数值,并且返回一个以 “MB”、”GB” 或 “PB” 为单位的,格式良好的大小值。
1 | function Get-DisplayFileSize |
以下是一些例子:
1 | PS> Get-DisplayFileSize -Number 800 |
真正有趣的地方是这个函数返回的并不是字符串。它返回的是原始的数值,而只是覆盖了 ToString()
方法。您仍然可以对它进行排序、计算和对比:
1 | PS> $n = 1245646233213 |
您可能还没有注意到,Get-ChildItem
(也叫做 dir
或者 ls
) 的 -Filter
参数并不是像您所想的方式工作。以下代码的本意是只查找 PowerShell 脚本,但实际上找到的结果更多:
1 | Get-ChildItem -Path $env:windir -Filter *.ps1 -Recurse -ErrorAction Silent | |
以下是查找结果:
1 | Count Name |
-Filter
参数的作用和传统的 dir
命令的行为类似。要真正起到您想要的效果,您应该使用以下代码:
1 | Get-ChildItem -Path $env:windir -Filter *.ps1 -Include *.ps1 -Recurse -ErrorAction SilentlyContinue | |
以下是正确的结果:
1 | Count Name |
虽然您可以省略 -Filter
参数,但强烈建议保留着它。首先,-Include
只能和 -Recurse
配合使用其次,-Include
速度很慢。先用一个粗略(但是快速)的 -Filter
过滤,然后用 Include
是最佳实践。
在前一个技能中我们介绍了 ConvertObject-ToHashTable
函数,它能方便地将对象显示在一个网格视图窗口中。
以下代码是一个改进的版本,能够根据字母顺序排列属性,并且可以由您决定每一列的名称。缺省情况下,Out-GridView
的列名为 “Property” 和 “Value”,但您将它们改为任意名称:
1 | function ConvertObject-ToHashTable |
Out-GridView
是一个有用的 cmdlet。但如果只是用它来显示一个单一对象的所有属性时不太理想,因为这样显示出来只有一行。在前一个技能中我们解释了将一个对象转换为一个哈希表能解决这个问题。它实际上是将一个网格视图工作在“列表视图”模式。
因为这个方法在许多场景中十分有用,以下是一个封装好的名为 ConvertObject-ToHashTable
的函数,以及一系列示例代码:
1 | function ConvertObject-ToHashTable |
一个最简单的硬件清单功能可以用一行代码实现:
1 | $data = systeminfo.exe /FO CSV | ConvertFrom-Csv |
一个更现代的方法是使用新的 Get-ComputerInfo
cmdlet:
1 | $data = Get-ComputerInfo |
一个最简单方法是用 Group-Object 创建一个哈希表:将原始数据用某个属性,例如
UserName` 来分组。然后,在网格视图窗口中显示哈希表的键。当用户选择了一个对象时,将选中的项目作为哈希表的键,找到原始项目:
1 | $data = Get-ComputerInfo |
现在网格视图窗口以更好的方式显示信息。这段代码用 Get-Member
来查找信息对象 $data
中暴露的属性名。它接下来创建一个哈希表,每个属性代表一个键,每个值代表一个属性值。
本质上,网格视图窗口现在显示的是多个键值对,而不是单一的一个对象。
在前一个技能中我们演示了如何用 PowerShell 命令模式方便地创建引号包围的字符串列表。这可以很方便地创建代码,节省很多打字工作。
以下是一个在日常 PowerShell 编码工作中有用的函数:
1 | function s+ { "'$($args -join "','")'" | Set-ClipBoard } |
下一次您在代码中需要一个引号包围的字符串列表时,只需要键入:
1 | PS> s+ start stop pause end whatever |
执行完之后,引号包围的字符串就会存在您的剪贴板中,接下来您可以将它们粘贴到任何需要的地方。
这是一个非常简单的创建引号包起来的字符串的列表的例子:
1 | & { "'$($args -join "','")'" } hello this is a test |
以下是执行结果:
1 | 'hello','this','is','a','test' |
这个例子有效利用了 PowerShell 的“命令模式”,字面量被当作参数使用。您还可以将结果通过管道导出到 Set-Clipboard
指令执行,然后将结果贴回代码中。这比起手工为每个字符串添加引号方便多了。
1 | PS> & { "'$($args -join "','")'" } hello this is a test | Set-ClipBoard |
在前一个技能中我们介绍了如何使用哈希表来显示简单的选择对话框,而当用户选择了一个对象时,返回完整的对象。
哈希表基本上可以使用任何数据作为键。在前一个例子中,我们使用字符串作为键。它也可以是其它对象。这可以让您做选择对话框的时候十分灵活。
只需要使用 Select-Object
来选择希望在网格视图窗口中显示的属性,并且用它来作为哈希表的键。
1 | # create a hash table where the key is the selected properties to display, |
当您运行这段代码时,网格视图窗口显示一个网络适配器的列表,并且只显示选择的属性 (Description、IPAddress 和 MacAddress)。
当用户选择了一个元素,这段代码返回原始的(完整)对象。这样即便网格视图窗口显示的是对象的一部分,整个对象任然可以用。
如何使用网格视图窗口作为一个简单的选择对话框呢?
当您将对象用管道输出到网格视图窗口中,所有属性都会显示出来。通常情况下这可以工作得很好,只需要这样一行代码:
1 | Get-Service | Out-GridView -Title "Select Service" -OutputMode Single |
有些时候,特别是一个对象有诸多属性时,可能会让用户看不过来:
1 | Get-WmiObject -Class Win32_NetworkAdapterConfiguration | |
要简化这个对话框,您可以使用我们之前在用户配置文件管理中的方法,使用一个哈希表。只需要选择一个属性作为键。这个属性必须是唯一的。接下来,试试这段代码:
1 | Get-WmiObject -Class Win32_NetworkAdapterConfiguration | |
如您所见,只有选择中的属性会在网格视图窗口中显示,当用户选择了一个元素,将获取到完整的对象。这和服务列表的工作方式很像:
1 | $hashTable = Get-Service | |