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> ] ...}
PowerShell 3.0 中引入了 [ordered]
类型加速器。
若要创建, 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.
若要更正表达式,请移动 [ordered] 属性。
$orderedhash = [ordered]@{}
可以将有序字典强制转换为 a 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、 Keys、 Values 和 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 = @{}
可以使用数组表示法添加键值对。 例如,以下示例向 添加一个Time
值为 的Now
hashtable键。
$hash["Time"] = "Now"
还可以使用Add()
对象的方法System.Collections.Hashtable向 Add()
方法采用以下语法:
Add(Key, Value)
例如,若要添加值为 Now
hashtable键,请使用以下语句格式。
$hash.Add("Time", "Now")
此外,还可以使用加法运算符 (+
) hashtable 向hashtable现有hashtable运算符添加键和值。 例如,以下语句将一个Time
键添加到变量$hash
中的值Now
hashtable。
$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 中的键和值可以具有任何 .NET 对象类型,一 hashtable 个可以具有多个类型的键和值。
以下语句创建 hashtable 进程名称字符串和进程对象值,并将其保存在变量中 $p
。
$p = @{
"PowerShell" = (Get-Process PowerShell)
"Notepad" = (Get-Process notepad)
}
可以显示 hashtable in $p
并使用键名称属性来显示值。
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)
System.ServiceProcess.Servi... 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 键是字符串、Hash2 的变量中的 $p
键值对,值是具有三个 hashtable 键值对。
$p = $p + @{
"Hash2"= @{a=1; b=2; c=3}
}
可以使用相同的方法显示和访问新值。
PS> $p
Name Value
---- -----
PowerShell System.Diagnostics.Process (pwsh)
Hash2 {[a, 1], [b, 2], [c, 3]}
Notepad System.Diagnostics.Process (Notepad)
WinRM Running
PS> $p.Hash2
Name Value
---- -----
a 1
b 2
c 3
PS> $p.Hash2.b
2
对键和值进行排序
中的 hashtable 项本质上是无序的。 每次显示键值对时,它们可能会以不同的顺序显示。
虽然无法排序, hashtable但可以使用 GetEnumerator()
哈希表方法枚举键和值,然后使用 Sort-Object
cmdlet 对枚举值进行排序以显示。
例如,以下命令枚举 $p
变量中哈希表的键和值,然后按字母顺序对键进行排序。
PS> $p.GetEnumerator() | Sort-Object -Property key
Name Value
---- -----
Hash2 {[a, 1], [b, 2], [c, 3]}
Notepad System.Diagnostics.Process (Notepad)
PowerShell System.Diagnostics.Process (pwsh)
WinRM Running
以下命令使用相同的过程按降序对哈希值进行排序。
PS> $p.GetEnumerator() | Sort-Object -Property Value -Descending
Name Value
---- -----
PowerShell System.Diagnostics.Process (pwsh)
Notepad System.Diagnostics.Process (Notepad)
Hash2 {[a, 1], [b, 2], [c, 3]}
WinRM Running
从哈希表创建对象
从 PowerShell 3.0 开始,可以从属性和属性值创建对象 hashtable 。
语法如下:
[<class-name>]@{
<property-name>=<property-value>
<property-name>=<property-value>
}
此方法仅适用于具有无参数构造函数的类。 对象属性必须是公共且可设置的。
有关详细信息,请参阅 about_Object_Creation。
ConvertFrom-StringData
该 cmdlet 将 ConvertFrom-StringData
字符串或此处键值对的字符串转换为一个 hashtable。 可以在脚本的 Data 部分安全地使用 ConvertFrom-StringData
cmdlet,并且可以将其与 Import-LocalizedData
cmdlet 配合使用,以当前用户的用户界面 (UI) 区域性显示用户消息。
当包含引号中的 hashtable 值时,此处字符串特别有用。 有关 here-string 的详细信息,请参阅 about_Quoting_Rules。
以下示例演示如何在上一示例中创建用户消息的此处字符串,以及如何使用 ConvertFrom-StringData
它们从字符串转换为字符串 hashtable。
以下命令创建键值对的 here-string,然后将其保存在 $string
变量中。
$string = @"
Msg1 = Type "Windows".
Msg2 = She said, "Hello, World."
Msg3 = Enter an alias (or "nickname").
"@
此命令使用 ConvertFrom-StringData
cmdlet 将此处的字符串转换为 .hashtable
ConvertFrom-StringData $string
Name Value
---- -----
Msg3 Enter an alias (or "nickname").
Msg2 She said, "Hello, World."
Msg1 Type "Windows".
有关 here-string 的详细信息,请参阅 about_Quoting_Rules。