关于哈希表
简短说明
介绍如何在 PowerShell 中创建、使用和排序哈希表。
详细说明
哈希表也称为字典或关联数组,是存储一个或多个键/值对的紧凑数据结构。 例如,哈希表可能包含一系列 IP 地址和计算机名称,其中 IP 地址是键,计算机名称是值,反之亦然。
在 PowerShell 中,每个哈希表都是一个 Hashtable (System.Collections.Hashtable) 对象。 可以在 PowerShell 中使用 Hashtable 对象的属性和方法。
从 PowerShell 3.0 开始,可以使用 [ordered] 属性在 PowerShell 中 (System.Collections.Specialized.OrderedDictionary) 创建有序字典。
有序字典与哈希表的不同之处在于,键始终按列出顺序显示。 哈希表中键的顺序未确定。
哈希表中的键和值也是 .NET 对象。 它们通常是字符串或整数,但它们可以具有任何对象类型。 还可以创建嵌套哈希表,其中键的值是另一个哈希表。
经常使用哈希表,因为它们非常高效地查找和检索数据。 可以使用哈希表在 PowerShell 中存储列表和创建计算属性。 而且,PowerShell 有一个 cmdlet ConvertFrom-StringData,用于将字符串转换为哈希表。
语法
哈希表的语法如下所示:
@{ <name> = <value>; [<name> = <value> ] ...}
有序字典的语法如下所示:
[ordered]@{ <name> = <value>; [<name> = <value> ] ...}
[有序] 属性是在 PowerShell 3.0 中引入的。
创建哈希表
若要创建哈希表,请遵循以下准则:
- 使用 at 符号 (@) 开始哈希表。
- 将哈希表括在大括号 ({}) 。
- 为哈希表的内容输入一个或多个键/值对。
- 使用等号 (=) 将每个键与其值分开。
- 使用分号 (;) 或换行符分隔键/值对。
- 包含空格的键必须用引号引起来。 值必须是有效的 PowerShell 表达式。 字符串必须出现在引号中,即使它们不包含空格。
- 若要管理哈希表,请将其保存在变量中。
- 将有序哈希表分配给变量时,请将 [ordered] 属性放在“@”符号之前。 如果将它置于变量名称之前,则命令将失败。
若要在 $hash 的值中创建空哈希表,请键入:
$hash = @{}
还可以在创建哈希表时向其添加键和值。 例如,以下语句创建一个包含三个键的哈希表。
$hash = @{ Number = 1; Shape = "Square"; Color = "Blue"}
创建有序字典
可以通过添加 OrderedDictionary 类型的对象来创建有序字典,但创建有序字典的最简单方法是使用 [Ordered] 属性。
[有序] 属性在 PowerShell 3.0 中引入。
将 属性放在“@”符号前面。
$hash = [ordered]@{ Number = 1; Shape = "Square"; Color = "Blue"}
可以采用与使用哈希表相同的方式使用有序字典。 任一类型都可以用作采用哈希表或字典的参数的值, (iDictionary) 。
不能使用 [有序] 属性转换或强制转换哈希表。 如果将有序属性置于变量名称之前,则命令将失败并显示以下错误消息。
PS C:\> [ordered]$hash = @{}
At line:1 char:1
+ [ordered]$hash = @{}
+ [!INCLUDE[]()]
The ordered attribute can be specified only on a hash literal node.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordExc
eption
+ FullyQualifiedErrorId : OrderedAttributeOnlyOnHashLiteralNode
若要更正表达式,请移动 [有序] 属性。
PS C:\> $hash = [ordered]@{}
可以将有序字典强制转换为哈希表,但无法恢复有序属性,即使清除变量并输入新值也是如此。 若要重新建立顺序,必须删除并重新创建变量。
PS C:\> [hashtable]$hash = [ordered]@{
>> Number = 1; Shape = "Square"; Color = "Blue"}
PS C:\> $hash
Name Value
---- -----
Color Blue
Shape Square
Number 1
显示哈希表
若要显示保存在变量中的哈希表,请键入变量名称。 默认情况下,哈希表显示为表,其中一列用于键,一列表示值。
C:\PS> $hash
Name Value
---- -----
Shape Square
Color Blue
Number 1
哈希表具有 Keys 和 Values 属性。 使用点表示法显示所有键或所有值。
C:\PS> $hash.keys
Number
Shape
Color
C:\PS> $hash.values
1
Square
Blue
每个键名称也是哈希表的一个属性,其值是键名称属性的值。 使用以下格式显示属性值。
$hashtable.<key>
<value>
例如:
C:\PS> $hash.Number
1
C:\PS> $hash.Color
Blue
如果键名称与 HashTable 类型的某个属性名称冲突,则可以使用 PSBase
来访问这些属性。 例如,如果密钥名称为 keys
,并且你想要返回 Keys 的集合,请使用以下语法:
$hashtable.PSBase.Keys
哈希表具有 Count 属性,该属性指示哈希表中键值对的数目。
C:\PS> $hash.count
3
哈希表不是数组,因此不能使用整数作为哈希表中的索引,但可以使用键名称为哈希表编制索引。 如果键是字符串值,请将密钥名称用引号引起来。
例如:
C:\PS> $hash["Number"]
1
添加和删除键和值
若要向哈希表添加键和值,请使用以下命令格式。
$hash["<key>"] = "<value>"
例如,若要将值为“Now”的“Time”键添加到哈希表,请使用以下语句格式。
$hash["Time"] = "Now"
还可以使用 System.Collections.Hashtable 对象的 Add 方法将键和值添加到哈希表。 Add 方法具有以下语法:
Add(Key, Value)
例如,若要将值为“Now”的“Time”键添加到哈希表,请使用以下语句格式。
$hash.Add("Time", "Now")
此外,可以使用加法运算符 (+) 将哈希表添加到现有哈希表,从而向哈希表添加键和值。 例如,下面的语句将值为“Now”的“Time”键添加到 $hash 变量中的哈希表中。
$hash = $hash + @{Time="Now"}
还可以添加存储在变量中的值。
$t = "Today"
$now = (Get-Date)
$hash.Add($t, $now)
不能使用减法运算符从哈希表中删除键/值对,但可以使用 Hashtable 对象的 Remove 方法。 Remove 方法将键作为其值。
Remove 方法具有以下语法:
Remove(Key)
例如,若要从哈希表中的 $hash 变量的值中删除 Time=Now 键/值对,请键入:
$hash.Remove("Time")
可以在 PowerShell 中使用 Hashtable 对象的所有属性和方法,包括 Contains、Clear、Clone 和 CopyTo。 有关 Hashtable 对象的详细信息,请参阅 System.Collections.Hashtable。
HashTable 中的对象类型
哈希表中的键和值可以具有任何 .NET 对象类型,单个哈希表可以具有多种类型的键和值。
以下语句创建进程名称字符串和处理对象值的哈希表,并将其保存在 变量中 $p
。
$p = @{"PowerShell" = (Get-Process PowerShell);
"Notepad" = (Get-Process notepad)}
可以在 中 $p
显示哈希表,并使用键名称属性来显示值。
C:\PS> $p
Name Value
---- -----
PowerShell System.Diagnostics.Process (PowerShell)
Notepad System.Diagnostics.Process (notepad)
C:\PS> $p.PowerShell
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
441 24 54196 54012 571 5.10 1788 PowerShell
C:\PS> $p.keys | foreach {$p.$_.handles}
441
251
哈希表中的键也可以是任何 .NET 类型。 以下语句将键/值对添加到 变量中的 $p
哈希表。 键是表示 WinRM 服务的 Service 对象,值是服务的当前状态。
C:\PS> $p = $p + @{(Get-Service WinRM) = ((Get-Service WinRM).Status)}
可以使用与哈希表中其他对相同的方法来显示和访问新的键/值对。
C:\PS> $p
Name Value
---- -----
PowerShell System.Diagnostics.Process (PowerShell)
Notepad System.Diagnostics.Process (notepad)
System.ServiceProcess.Servi... Running
C:\PS> $p.keys
PowerShell
Notepad
Status Name DisplayName
------ ---- -----------
Running winrm Windows Remote Management (WS-Manag...
C:\PS> $p.keys | foreach {$_.name}
winrm
哈希表中的键和值也可以是哈希表对象。 以下语句将键/值对添加到变量中的 $p
哈希表,其中键是字符串 Hash2,值是具有三个键/值对的哈希表。
C:\PS> $p = $p + @{"Hash2"= @{a=1; b=2; c=3}}
可以通过使用相同的方法显示和访问新值。
C:\PS> $p
Name Value
---- -----
PowerShell System.Diagnostics.Process (PowerShell)
Notepad System.Diagnostics.Process (notepad)
System.ServiceProcess.Servi... Running
Hash2 {a, b, c}
C:\PS> $p.Hash2
Name Value
---- -----
a 1
b 2
c 3
C:\PS> $p.Hash2.b
2
对键和值进行排序
哈希表中的项本质上是无序的。 每次显示键/值对时,它们可能以不同的顺序显示。
尽管不能对哈希表进行排序,但可以使用哈希表的 GetEnumerator 方法枚举键和值,然后使用 Sort-Object cmdlet 对枚举值进行排序,以便显示。
例如,以下命令枚举变量中哈希表中的键和值, $p
然后按字母顺序对键进行排序。
C:\PS> $p.GetEnumerator() | Sort-Object -Property key
Name Value
---- -----
Notepad System.Diagnostics.Process (notepad)
PowerShell System.Diagnostics.Process (PowerShell)
System.ServiceProcess.Servi... Running
以下命令使用相同的过程按降序对哈希值进行排序。
C:\PS> $p.getenumerator() | Sort-Object -Property Value -Descending
Name Value
---- -----
PowerShell System.Diagnostics.Process (PowerShell)
Notepad System.Diagnostics.Process (notepad)
System.ServiceProcess.Servi... Running
从哈希表创建对象
从 PowerShell 3.0 开始,可以从属性和属性值的哈希表创建对象。
语法如下所示:
[<class-name>]@{
<property-name>=<property-value>
<property-name>=<property-value>
}
此方法仅适用于具有 null 构造函数(即,没有参数的构造函数)的类。 对象属性必须是公共且可设置的。
有关详细信息,请参阅 about_Object_Creation。
ConvertFrom-StringData
cmdlet ConvertFrom-StringData
将字符串或键/值对的 here 字符串转换为哈希表。 可以在脚本的 ConvertFrom-StringData
“数据”部分中安全地使用 cmdlet,并且可以将其与 cmdlet 一起使用 Import-LocalizedData
,以在用户界面 (UI 中显示用户消息,) 当前用户的区域性。
当哈希表中的值包含引号时,Here-string 特别有用。 有关 here-strings 的详细信息,请参阅 about_Quoting_Rules。
以下示例演示如何创建上一示例中用户消息的 here 字符串,以及如何使用 ConvertFrom-StringData
将其从字符串转换为哈希表。
以下命令创建键/值对的 here 字符串,然后将其保存在 $string 变量中。
C:\PS> $string = @"
Msg1 = Type "Windows".
Msg2 = She said, "Hello, World."
Msg3 = Enter an alias (or "nickname").
"@
此命令使用 ConvertFrom-StringData cmdlet 将 here-string 转换为哈希表。
C:\PS> ConvertFrom-StringData $string
Name Value
---- -----
Msg3 Enter an alias (or "nickname").
Msg2 She said, "Hello, World."
Msg1 Type "Windows".
有关 here-strings 的详细信息,请参阅 about_Quoting_Rules。