Powershell 将哈希表转换为字符串数组

Powershell 将哈希表转换为字符串数组,powershell,Powershell,如何将哈希表转换为字符串数组? 假设$l_表是一个哈希表。如果我尝试 $l_array = $l_table | format-table $l_array = $l_table | out-string 那么$l_数组是一个数组,但却是一个“FormatEntryData”对象的数组。 如果我这样做 [string[]]$l_array = $l_table | format-table 那么$l_数组是一个字符串数组,但是字符串都是“Microsoft.PowerShell.Comma

如何将哈希表转换为字符串数组? 假设$l_表是一个哈希表。如果我尝试

$l_array = $l_table | format-table
$l_array = $l_table | out-string
那么$l_数组是一个数组,但却是一个“FormatEntryData”对象的数组。 如果我这样做

[string[]]$l_array = $l_table | format-table
那么$l_数组是一个字符串数组,但是字符串都是“Microsoft.PowerShell.Commands.Internal.Format.FormatteryData”。如果我尝试

$l_array = $l_table | out-string

那么$l_数组就是一个字符串。我尝试了很多其他方法,但除了手动循环外,没有任何效果,我真的不想这样做。

哈希表只是一个哈希表,所以它有一个键和一个值属性

$hash = @{}

$hash["foo"] = "bob"

$hash.Values

$hash.Values | Out-string

如果要获取枚举数,它将返回keyvaluepair

$hash.GetEnumerator() |%{$_ | out-string}
工作正常,但应注意,结果数组的元素对应于默认输出的所有行,其中包括:

  • 空的前导行和尾随行
  • 两个标题行(带列名的行和分隔行)
输出字符串
只需将您通常在控制台(终端)中看到的内容发送到字符串,默认情况下为单个字符串,并使用
-Stream
作为字符串数组

下面是David命令的一个变体,它删除了标题和空行:

[string[]$l_数组=($l_table | Out string-Stream)-ne''选择-跳过2

这个答案的其余部分显示了如何控制获得的字符串表示的细节;它使用PS v3+语法和内置别名
%
表示
ForEach对象
,以简洁明了

注意:为清楚起见,在以下示例中,示例输入哈希表称为
$ht
(不是
$l_table
);PSv4+
.ForEach()
变体的性能更好

  • 获取所有键作为字符串数组:

      $ht.Keys | % ToString # or (PSv4+): $ht.Keys.ForEach('ToString')
    
      $ht.Values | % ToString # or (PSv4+): $ht.Values.ForEach('ToString')
    
  • 获取所有值作为字符串数组:

      $ht.Keys | % ToString # or (PSv4+): $ht.Keys.ForEach('ToString')
    
      $ht.Values | % ToString # or (PSv4+): $ht.Values.ForEach('ToString')
    
  • 获取键值对的自定义表示形式,格式为
    =
    ;请注意,需要
    .GetEnumerator()
    通过管道单独发送键值对;默认情况下,PowerShell作为一个整体传递哈希表:

请注意,
.ToString()
,它也在字符串插值过程中隐式应用(在可扩展字符串的内部,
“…”
),可以很好地与.NET类型(以及其他数字类型,如
[decimal]
[bigint]
)配合使用;通常,类型将只打印其完整的类型名,除非显式重写其
.ToString()
方法以返回更有意义的自定义表示(这是基元类型所做的,并且只有PowerShell cmdlet返回的一些非基元类型才是这种情况)。
还请注意,在可扩展字符串中使用数组(-like data structure)可扩展为其元素与
$OFS
首选项变量值(默认为空格字符)的(字符串化)元素串联。(例如,
$a='one','two';“$a”
扩展为
'一两'
)-有关PowerShell中可扩展字符串(字符串插值)的更多信息,请参阅

选择值的属性以在字符串中表示它的一个简单示例:

# Sample hashtable containing a value of a non-built-in type,
# [System.Diagnostics.Process]    
$ht = @{ one = 1; two = Get-Process -ID $PID }

# Use the `.Path` property to represent the value.
$ht.GetEnumerator()  | % { "$($_.Name)=$($_.Value.Path)" }

这是一个普遍的问题;哈希表必须通过键或值进行检索,但不能获得对的集合——毕竟,这就是原始哈希表。在我的示例中,哈希表由“Dictionary”表示(您将从VBS中记住:-)。但是,您需要确定分隔符来分隔键和值,在本例中为“KeyValue”

$ARRAY=($DICT.Keys | foreach对象{“$\($DICT[$\])”)
如果需要,您甚至可以先对键进行排序。在本例中,我反转为ValueKey并按值排序。我还稍微扩展了字符串,使其更加详细但清晰:

$ARRAY = ( $DICT.Keys | foreach-object { $DICT[$_] + "<--->" + $_} | sort-object)
$ARRAY=($DICT.Keys | foreach对象{$DICT[$\]+“”+$\}排序对象)

虽然原始海报可能需要一个字符串数组,对应于格式表的输出,正如所提供的尝试和海报自己的回答/评论所表明的那样,问题标题的措辞更典型地是希望将哈希表本身转换为每个项目值的数组(如果还不是
字符串,则转换为
字符串
)。对于那些寻求解决此问题的方法的人,我提出以下内容(因为目前似乎还没有类似的问题):-

简单的答案是使用

[string[]]$l_table.values
这确实给出了所需的字符串数组

注意:
$l_table.values
是一个
[System.Collections.Hashtable+ValueCollection]
,这就是为什么即使值已经是字符串,也需要转换为
[string[]
。例如

'Found {0} with submatch {1}' -f [string[]]$matches.values
没有它就无法工作。(下一步将提到另一个可能的问题。)

$l_table.values
的主要缺陷在于,除非将哈希表定义为
[ordered]
(PSv3+),否则项的顺序未定义(并且可以随着哈希表的修改而更改)。通常,在将哈希表转换为数组时,需要该数组中的元素具有某种顺序。实际上,有时键是(正)整数,目的是生成的数组使用与数组索引相同的值(请参见上面的
$matches
示例)。要创建这种类型的数组,请使用

[string[]]$l_table[($l_table.keys | sort)]
或者,如果值已经是字符串,只需

$l_table[($l_table.keys | sort)]
调用Powershell的集合切片功能(通过使用数组表达式作为索引,单个表达式可以生成独立选择的集合项数组。例如,
$array[1,3,5,9]
$array[1,2,3,4,5]
$array[1,5]
)。请注意,如果键从0开始形成一个连续范围,则这将只生成一个以键作为索引的数组。但是
[string[]]$l_table[0..($l_table.keys | sort -descending)[0]]
#
# ($l_table.keys | sort -descending) produces a sorted array of key values
# with the largest value in element 0
#
($l_table.getenumerator() | foreach -begin {$str_table = @{}} -process {$str_table.add($_.key,[string]$_.value)} -end {$str_table[0..($str_table.keys | sort -descending)[0]]})
($l_table.getenumerator() | foreach -begin {$maxkey = 0; $str_table = @{}} -process {$str_table.add($_.key,[string]$_.value); if ($maxkey -lt $_.key){$maxkey = $_.key}} -end {$str_table[0..$maxkey]})
$l_table[0..($l_table.keys | sort -descending)[0]]