about_Hash_Tables

应用到: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0, Windows PowerShell 5.0

主题

about_Hash_Tables

简短说明

介绍如何创建、使用和排序 Windows PowerShell® 中的哈希表。

详细说明

哈希表(也称为字典和关联数组)是存储一个或多个键/值对的压缩数据结构。例如,一个哈希表可能包含一系列 IP 地址和计算机名称,其中 IP 地址是键,而计算机名称是值,反之亦然。

在 Windows PowerShell 中,每个哈希表都是一个 Hashtable (System.Collections.Hashtable) 对象。你可以使用 Windows PowerShell 中的 Hashtable 对象的属性和方法。

从 Windows PowerShell 3.0 开始,你可以使用 [ordered] 属性,在 Windows PowerShell 中创建有序的字典 (System.Collections.Specialized.OrderedDictionary)。

有序的字典与哈希表不同,区别在于键始终以你列出它们的顺序显示。不确定哈希表中的键的顺序。

哈希表中的键和值也是 .NET 对象。它们通常是字符串或整数,但它们可以具有任何对象类型。你还可以创建嵌套的哈希表,其中键的值是另一个哈希表。

通常使用哈希表,因为使用它们查找和检索数据非常高效。你可以使用哈希表存储列表和在 Windows PowerShell 中创建已计算的属性。并且,Windows PowerShell 具有可将字符串转换为哈希表的 ConvertFrom-StringData cmdlet。

语法

哈希表的语法如下所示:

          @{ <name> = <value>; [<name> = <value> ] ...}

有序字典的语法如下所示:

          [ordered]@{ <name> = <value>; [<name> = <value> ] ...}

Windows PowerShell 3.0 中引入了 [ordered] 属性。

创建哈希表

若要创建哈希表,请遵循这些指南:

- 以 at 符号 (@) 开始哈希表。

- 将哈希表放在大括号 ({}) 中。

- 为哈希表的内容输入一个或多个键/值对。

- 使用等号 (=) 将每个键与其值分隔开。

- 使用分号 (;) 或换行符来分隔键/值对。

- 包含空格的键必须括在引号内。值必须是有效的 Windows PowerShell 表达式。字符串必须显示在引号中,即使它们不包括空格。

- 若要管理哈希表,请将其保存在变量中。

- 当将有序的哈希表分配给一个变量时,请将 [ordered] 属性放在“@”符号前。如果你将其放在变量名称前,则命令将失败。

若要在 $hash 的值中创建空哈希表,请键入:

          $hash = @{}

你还可以在创建哈希表时向其添加键和值。例如,以下语句创建带有三个键的哈希表。

          $hash = @{ Number = 1; Shape = "Square"; Color = "Blue"}

创建有序字典

你可以通过添加 OrderedDictiory 类型的对象创建有序字典,但创建有序字典的最简单方法是使用 [Ordered] 属性。

Windows PowerShell 3.0 中引入了 [ordered] 属性。

紧挨在“@”符号前放置属性。

          $hash = [ordered]@{ Number = 1; Shape = "Square"; Color = "Blue"}

使用有序字典的方式与使用哈希表相同。两种类型都可用作采用哈希表或字典 (iDictionary) 的参数值。

你无法使用 [ordered] 属性转换或强制转换哈希表。如果你将有序属性放在变量名称前,则命令将失败并显示以下错误消息。

        PS C:\> [ordered]$hash = @{}
        At line:1 char:1
        + [ordered]$hash = @{}
        + ~~~~~~~~~~~~~~
        The ordered attribute can be specified only on a hash literal node.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : OrderedAttributeOnlyOnHashLiteralNode
    To correct the expression, move the [ordered] attribute.     
        PS C:\> $hash = [ordered]@{}

你可以将有序字典强制转换为哈希表,但你无法恢复有序属性,即使你清除该变量并输入新值。若要重新建立顺序,你必须删除并重新创建该变量。

        PS C:\> [hashtable]$hash = [ordered]@{ Number = 1; Shape = "Square"; Color = "Blue"}
        PS C:\ps-test> $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

哈希表具有一个 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 = $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")

你可以使用 Windows PowerShell 的 Hashtable 对象的所有属性和方法,包括 Contains、Clear、Clone 和 CopyTo。有关 Hashtable 对象的详细信息,请参阅 MSDN 上的“System.Collections.Hashtable”。

HashTables 中的对象类型

哈希表中的键和值可以具有任何 .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        

哈希表中的键和值也可以是 Hashtable 对象。以下语句将键/值对添加到 $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

从哈希表创建对象

从 Windows PowerShell 3.0 开始,你可以从属性和属性值的哈希表创建对象。

语法如下所示:

        [<class-name>]@{<property-name>=<property-value>;<property-name>=<property-value>}

此方法仅适用于具有空构造函数(即没有参数的构造函数)的类。对象属性必须是公共的且可设置。

有关详细信息,请参阅 about_Object_Creation。

ConvertFrom-StringData

ConvertFrom-StringData cmdlet 将键/值对的字符串或 here-string 转换为哈希表。你可以在脚本的 Data 部分中安全地使用 ConvertFrom-StringData cmdlet,并且可以将其与 Import-LocalizedData cmdlet 一起使用以在当前用户的用户界面 (UI) 区域性中显示用户消息。

当哈希表中的值包含引号时,Here-string 尤其有用。(有关 here-string 的详细信息,请参阅 about_Quoting_Rules。)

以下示例显示如何创建前面示例中的用户消息的 here-string,以及如何使用 ConvertFrom-StringData 将它们从字符串转换为哈希表。

以下命令创建键/值对的 here-string,然后将其保存在 $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-string 的详细信息,请参阅 about_Quoting_Rules。

另请参阅

about_Arrays

about_Object_Creation

about_Quoting_Rules

about_Script_Internationalization

ConvertFrom-StringData

Import-LocalizedData

MSDN 上的“System.Collections.Hashtable”