关于哈希表

简短说明

介绍如何在 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

另请参阅

about_Arrays

about_Object_Creation

about_Quoting_Rules

about_Script_Internationalization

ConvertFrom-StringData

Import-LocalizedData

System.Collections.Hashtable