共用方式為


about_Hash_Tables

簡短描述

描述如何在PowerShell中建立、使用和排序哈希表。

詳細描述

hashtable也稱為字典或關聯陣列,是儲存一或多個索引鍵/值組的精簡數據結構。 例如,哈希表可能包含一系列IP位址和計算機名稱,其中IP位址是索引鍵,而計算機名稱是值,反之亦然。

在 PowerShell 中,每個 hashtable 都是 [System.Collections.Hashtable] 物件。 您可以在 PowerShell 中使用 物件的屬性和方法 Hashtable

從 PowerShell 3.0 開始,您可以使用 [ordered] 類型加速器在 PowerShell 中建立 [System.Collections.Specialized.OrderedDictionary] 物件。

已排序的字典與哈希表不同,因為索引鍵一律會以您列出它們的順序顯示。 中的 hashtable 索引鍵順序不具決定性。

哈希表中的索引鍵和值也是 .NET 物件。 它們通常是字串或整數,但是可以有任何物件類型。 您也可以建立巢狀哈希表,其中索引鍵的值是另一個 hashtable。

哈希表經常使用,因為它們有效率地尋找和擷取數據。 您可以使用哈希表來儲存清單,並在PowerShell中建立匯出屬性。 而且,Cmdlet 會將 ConvertFrom-StringData 結構化字串資料 hashtable轉換成 。

語法

的 hashtable 語法如下所示:

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

已排序字典的語法如下所示:

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

類型 [ordered] 加速器是在PowerShell 3.0中引進的。

若要建立 hashtable,請遵循下列指導方針:

  • hashtable以符號 (@) 開頭。
  • 以 hashtable 大括弧 ({}) 括住 。
  • 針對的內容 hashtable輸入一或多個機碼/值組。
  • 使用等號 (=) 將每個索引鍵與其值分開。
  • 使用分號 (;) 或換行符隔索引鍵/值組。
  • 包含空格的索引鍵必須以引號括住。 值必須是有效的 PowerShell 表達式。 字串必須以引號顯示,即使字串不包含空格也一樣。
  • 若要管理 hashtable,請將它儲存在變數中。
  • 將已排序 hashtable 的 指派給變數時,請將 [ordered] 類型放在符號之前 @ 。 如果您將它放在變數名稱之前,命令會失敗。

您可以使用使用哈希表的相同方式來使用已排序的字典。 任一類型都可以當做接受 hashtable 或 字典 (iDictionary) 類型對象的參數值。

建立哈希表和已排序的字典

請考慮下列 hashtable 和已排序的字典範例:

$hash = @{
    1       = 'one'
    2       = 'two'
    'three' = 3
}
$hash
Name                           Value
----                           -----
three                          3
2                              two
1                              one

如您所見,中的 hashtable 索引鍵/值組不會依定義的順序呈現。

建立已排序字典最簡單的方式是使用 [ordered] 屬性。 將屬性放在符號正前 @

$dictionary = [ordered]@{
    1       = 'one'
    2       = 'two'
    'three' = 3
}
$dictionary
Name                           Value
----                           -----
1                              one
2                              two
three                          3

不同於哈希表,已排序的字典會維護索引鍵/值的順序。

轉換哈希表和已排序的字典

您無法使用 [ordered] 型別加速器來轉換或轉換 hashtable。 如果您在變數名稱之前放置已排序的屬性,命令會失敗,並出現下列錯誤訊息。

[ordered]$orderedhash = @{}
ParserError:
Line |
   1 |  [ordered]$orderedhash = @{}
     |  ~~~~~~~~~~~~~~
     | The ordered attribute can be specified only on a hash literal node.

若要更正表示式,請移動 [已排序] 屬性。

$orderedhash = [ordered]@{}

您可以將已排序的 hashtable字典轉換成 ,但無法保證成員的順序。

[hashtable]$newhash = [ordered]@{
    Number = 1
    Shape = "Square"
    Color = "Blue"
}
$newhash
Name                           Value
----                           -----
Color                          Blue
Shape                          Square
Number                         1

Hashtable 和字典屬性

哈希表和已排序的字典會共享數個屬性。 $hash請考慮先前範例中定義的和 $dictionary 變數。

$hash | Get-Member -MemberType Properties, ParameterizedProperty
   TypeName: System.Collections.Hashtable

Name           MemberType            Definition
----           ----------            ----------
Item           ParameterizedProperty System.Object Item(System.Object key) {get;set;}
Count          Property              int Count {get;}
IsFixedSize    Property              bool IsFixedSize {get;}
IsReadOnly     Property              bool IsReadOnly {get;}
IsSynchronized Property              bool IsSynchronized {get;}
Keys           Property              System.Collections.ICollection Keys {get;}
SyncRoot       Property              System.Object SyncRoot {get;}
Values         Property              System.Collections.ICollection Values {get;}
$dictionary | Get-Member -MemberType Properties, ParameterizedProperty
   TypeName: System.Collections.Specialized.OrderedDictionary

Name           MemberType            Definition
----           ----------            ----------
Item           ParameterizedProperty System.Object Item(int index) {get;set;},
                                     System.Object Item(System.Object key) {get;set;}
Count          Property              int Count {get;}
IsFixedSize    Property              bool IsFixedSize {get;}
IsReadOnly     Property              bool IsReadOnly {get;}
IsSynchronized Property              bool IsSynchronized {get;}
Keys           Property              System.Collections.ICollection Keys {get;}
SyncRoot       Property              System.Object SyncRoot {get;}
Values         Property              System.Collections.ICollection Values {get;}

最常使用的屬性是 Count、索引鍵Item。

  • Count 屬性,指出 物件中的索引鍵/值組數目。

  • Keys 屬性是 或 字典中hashtable索引鍵名稱的集合。

    PS> $hash.Keys
    three
    2
    1
    
    PS> $dictionary.Keys
    1
    2
    three
    
  • Values 屬性是 或 字典中hashtable值的集合。

    PS> $hash.Values
    3
    two
    one
    
    PS> $dictionary.Values
    one
    two
    3
    
  • Item 屬性是參數化屬性,會傳回您指定的專案值。 哈希表會使用索引鍵做為參數化屬性的參數,而字典預設會使用索引。 此差異會影響您存取每個類型值的方式。

存取值

存取 或字典中的 hashtable 值有兩種常見方式:成員表示法或陣列索引表示法。

  • 成員表示法 - 您可以使用索引鍵名稱做為物件的成員屬性來存取值。 例如:

    PS> $hash.1
    one
    
    PS> $dictionary.2
    two
    
  • 陣列索引表示法 - 您可以使用索引表示 法來存取值。 PowerShell 會將該表示法轉換成物件的 Item 參數化屬性呼叫。

    當您搭配哈希表使用索引表示法時,括弧內的值為索引鍵名稱。 如果索引鍵是字串值,請以引號括住索引鍵名稱。 例如:

    PS> $hash['three']
    3
    
    PS> $hash[2]
    2
    

    在此範例中,索引鍵值 2 不是值集合中的索引。 這是索引鍵/值組中的索引鍵值。 您可以藉由將索引編製至值集合來證明這一點。

    PS> ([array]$hash.Values)[2]
    one
    

    當您搭配字典使用索引表示法時,括弧內的值會根據其類型來解譯。 如果值是整數,則會將其視為值集合中的索引。 如果值不是整數,則會將其視為索引鍵名稱。 例如:

    PS> $dictionary[1]
    two
    PS> ([array]$dictionary.Values)[1]
    two
    PS> $dictionary[[object]1]
    one
    PS> $dictionary['three']
    3
    

    在此範例中,陣列值 [1] 是使用參數化屬性多載的值集合中的 Item(int index) 索引。 陣列值 [[object]1] 不是索引,而是使用 多載的 Item(System.Object key) 索引鍵值。

    注意

    當索引鍵值是整數時,這種行為可能會造成混淆。 可能的話,您應該避免在字典中使用整數索引鍵值。

處理屬性名稱衝突

如果索引鍵名稱與類型的其中一個屬性名稱 HashTable 相衝突,您可以使用 psbase 內部成員 來存取這些屬性。 例如,如果索引鍵名稱是 keys ,而且您想要傳回索引鍵的 HashTable 集合,請使用下列語法:

$hashtable.psbase.Keys

此需求適用於實作 介面的其他類型 System.Collections.IDictionary ,例如 OrderedDictionary

逐一查看索引鍵和值

您可以逐一查看 中的 hashtable 索引鍵,以數種方式處理值。 本節中的每個範例都有相同的輸出。 他們會逐一查看 $hash 這裡定義的變數:

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

注意

在這些範例中, $hash 會定義為已排序的字典,以確保輸出一律以相同順序。 這些範例適用於標準哈希表,但無法預測輸出的順序。

每個範例都會傳回每個索引鍵及其值的訊息:

The value of 'Number' is: 1
The value of 'Shape' is: Square
The value of 'Color' is: Blue

此範例會使用 區塊逐一 foreach 查看金鑰。

foreach ($Key in $hash.Keys) {
    "The value of '$Key' is: $($hash[$Key])"
}

此範例會使用 ForEach-Object 來逐一查看索引鍵。

$hash.Keys | ForEach-Object {
    "The value of '$_' is: $($hash[$_])"
}

這個範例會 GetEnumerator() 使用 方法,透過管線將每個機碼/值組傳送至 ForEach-Object

$hash.GetEnumerator() | ForEach-Object {
    "The value of '$($_.Key)' is: $($_.Value)"
}

此範例會使用 GetEnumerator()ForEach() 方法來逐一查看每個機碼/值組。

$hash.GetEnumerator().ForEach({"The value of '$($_.Key)' is: $($_.Value)"})

新增和移除索引鍵和值

一般而言,當您建立 hashtable 時,會在定義中包含機碼/值組。 不過,您可以隨時從 hashtable 新增和移除機碼/值組。 下列範例會建立空 hashtable的 。

$hash = @{}

您可以使用陣列表示法來新增索引鍵/值組。 例如,下列範例會將 值為 Now 的hashtable索引鍵新增Time至 。

$hash["Time"] = "Now"

您也可以使用 Add() 物件的 方法System.Collections.Hashtable,將索引鍵和值新增至 hashtable 。 方法 Add() 具有下列語法:

Add(Key, Value)

例如,若要將 值為 Now 的索引鍵新增Time至 hashtable,請使用下列語句格式。

$hash.Add("Time", "Now")

此外,您可以使用加法運算子 (+) 將 新增至hashtable現有的 hashtable,將 索引鍵和值新增hashtable至 。 例如,下列語句會將 值為 Now 的索引鍵新增Time至 hashtable 變數中的 $hash

$hash = $hash + @{Time="Now"}

您也可以新增儲存在變數中的值。

$t = "Today"
$now = (Get-Date)

$hash.Add($t, $now)

您無法使用減法運算符從哈希表移除索引鍵/值組,但您可以使用 Remove() 物件的 方法 hashtable 。 方法 Remove 具有下列語法:

$object.Remove(<key>)

下列範例會 Time$hash中移除機碼/值組。

$hash.Remove("Time")

HashTable 中的物件類型

中的 hashtable 索引鍵和值可以具有任何 .NET 物件類型,而單 hashtable 一可以具有多個類型的索引鍵和值。

下列語句會 hashtable 建立進程名稱字串和進程物件值的,並將它儲存在變數中 $p

$p = @{
    "PowerShell" = (Get-Process PowerShell)
    "Notepad" = (Get-Process notepad)
}

您可以在 中$p顯示 hashtable ,並使用索引鍵名稱屬性來顯示值。

PS> $p

Name                           Value
----                           -----
PowerShell                     System.Diagnostics.Process (PowerShell)
Notepad                        System.Diagnostics.Process (notepad)

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

PS> $p.keys | ForEach-Object {$p.$_.handles}
441
251

中的 hashtable 索引鍵可以是任何 .NET 類型。 下列語句會將索引鍵/值組新增至 hashtable 變數中的 $p 。 索引鍵是 代表 WinRM 服務的 Service 物件,而值是服務的目前狀態。

$p = $p + @{
    (Get-Service WinRM) = ((Get-Service WinRM).Status)
}

您可以使用 中用於其他配對的相同方法來顯示和存取新的索引鍵/值組 hashtable。

PS> $p

Name                           Value
----                           -----
PowerShell                     System.Diagnostics.Process (powershell)
Notepad                        System.Diagnostics.Process (Notepad)
WinRM                          Running

PS> $p.keys
PowerShell
Notepad

Status   Name               DisplayName
------   ----               -----------
Running  winrm              Windows Remote Management (WS-Manag...

PS> $p.keys | ForEach-Object {$_.name}
WinRM

中的 hashtable 索引鍵和值也可以是 Hashtable 物件。 下列語句會將索引鍵/值組新增至 hashtable 變數中的 $p ,其中索引鍵為字串 Hash2,而值是 hashtable 具有三個索引鍵/值組的 。

$p = $p + @{
    "Hash2"= @{a=1; b=2; c=3}
}

您可以使用相同的方法來顯示和存取新值。

PS> $p

Name                           Value
----                           -----
PowerShell                     System.Diagnostics.Process (powershell)
Notepad                        System.Diagnostics.Process (Notepad)
WinRM                          Running
Hash2                          {c, b, a}

PS> $p.Hash2

Name                           Value
----                           -----
c                              3
b                              2
a                              1

PS> $p.Hash2.b
2

排序索引鍵和值

中的 hashtable 項目本質上是未排序的。 每次顯示索引鍵/值組時,可能會以不同的順序顯示。

雖然您無法排序 hashtable,但您可以使用 GetEnumerator() 哈希表的 方法來列舉索引鍵和值,然後使用 Sort-Object Cmdlet 來排序要顯示的列舉值。

例如,下列命令會列舉變數中哈希表中 $p 的索引鍵和值,然後依字母順序排序索引鍵。

PS> $p.GetEnumerator() | Sort-Object -Property key

Name                           Value
----                           -----
Hash2                          {c, b, a}
Notepad                        System.Diagnostics.Process (Notepad)
PowerShell                     System.Diagnostics.Process (powershell)
WinRM                          Running

下列命令使用相同的程式,以遞減順序排序哈希值。

PS> $p.GetEnumerator() | Sort-Object -Property Value -Descending

Name                           Value
----                           -----
PowerShell                     System.Diagnostics.Process (powershell)
Notepad                        System.Diagnostics.Process (Notepad)
Hash2                          {c, b, a}
WinRM                          Running

從哈希表建立物件

從 PowerShell 3.0 開始,您可以從 屬性和屬性值的 建立 物件 hashtable 。

語法如下所示:

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

這個方法只適用於具有沒有參數之建構函式的類別。 物件屬性必須是公用和可設定的。

如需詳細資訊,請參閱 about_Object_Creation

ConvertFrom-StringData

Cmdlet 會將 ConvertFrom-StringData 字串或索引鍵/值組的 here-string 轉換成 hashtable。 您可以在腳本的 [數據] 區段中安全地使用 ConvertFrom-StringData Cmdlet,而且可以搭配 Import-LocalizedData Cmdlet 在目前使用者的使用者介面 (UI) 文化特性中顯示使用者訊息。

當 include 引號中的 hashtable 值時,這裡字串特別有用。 如需 here-strings 的詳細資訊,請參閱 about_Quoting_Rules

下列範例示範如何在上一個範例中建立使用者訊息的 here-string,以及如何使用 ConvertFrom-StringData 將其從字串轉換成 hashtable。

下列命令會建立機碼/值組的 here-string,然後將它儲存在 變數中 $string

$string = @"
Msg1 = Type "Windows".
Msg2 = She said, "Hello, World."
Msg3 = Enter an alias (or "nickname").
"@

這個指令會 ConvertFrom-StringData 使用 Cmdlet 將 here-string hashtable轉換成 。

ConvertFrom-StringData $string

Name                           Value
----                           -----
Msg3                           Enter an alias (or "nickname").
Msg2                           She said, "Hello, World."
Msg1                           Type "Windows".

如需 here-strings 的詳細資訊,請參閱 about_Quoting_Rules

另請參閱