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

ryhaxcpt  于 2023-03-30  发布在  Shell
关注(0)|答案(5)|浏览(175)

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

$l_array = $l_table | format-table

然后$l_array是一个数组,但是是一个“FormatEntryData”对象的数组。如果我这样做

[string[]]$l_array = $l_table | format-table

然后$l_array是一个字符串数组,但字符串都是“Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData”。如果我尝试

$l_array = $l_table | out-string

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

wswtfjt7

wswtfjt71#

David I. McIntosh's own answer运行良好,但需要注意的是,结果数组的元素对应于默认输出的 * 所有 * 行,其中包括:

  • 空白的前导行和尾随行
  • 两个标题行(包含列名的行和分隔行)

Out-String只是将您通常在控制台(终端)中看到的内容发送到一个字符串,默认情况下为 * 单个 * 字符串,而-Stream则为字符串(行)的 * 数组 *。
下面是大卫命令的一个变体,它删除了标题和空行:

[string[]] $l_array = ($l_table | Out-String -Stream) -ne '' | select -Skip 2

这个答案的其余部分展示了如何 * 控制获得的字符串表示的细节;它使用PS v3+语法和内置别名%来表示ForEach-Object,以保持简洁。
注意:为了清楚起见,在下面的示例中,示例输入哈希表被称为$ht(而不是$l_table);PSv 4 + .ForEach()变体的性能更好。

  • 获取所有key作为字符串数组:
[string[]] $ht.Keys
  • 获取所有作为字符串数组:
[string[]] $ht.Values
  • 获取键值对自定义表示,格式为<key>=<value>;注意,需要.GetEnumerator()来通过流水线 * 单独地 * 发送键值对;默认情况下,PowerShell将哈希表 * 作为一个整体 * 传递:
$ht.GetEnumerator() | % { "$($_.Name)=$($_.Value)" }

  # or (PSv4+):
  $ht.GetEnumerator().ForEach({ "$($_.Name)=$($_.Value)" })

请注意,虽然[string]/[string[]]转换(也在字符串插值期间 * 隐式 * 应用)(在"..."内部,可扩展字符串),与primitive.NET类型(以及其他数字类型,如[decimal][bigint])配合良好;通常,类型将只打印其完整的 * 类型名称 *,除非显式重写其.ToString()方法以返回更有意义的自定义表示(这是原始类型所做的,并且仅是PowerShell cmdlet返回的 * 一些 * 非原始类型的情况)。
还请注意,在可扩展字符串中使用数组(类似于-的数据结构)可以扩展为(字符串化的)元素,将其元素与(很少使用的)$OFS首选项变量的值连接在一起,该变量默认为空格字符(例如,$a='one', 'two'; "$a"扩展为'one two';也就是说,它相当于"$([string[]] $a -join ' ')"-有关PowerShell中 * 可扩展字符串 *(字符串插值)的更多信息,请参见this answer
一个简单的例子,选择一个值的 * 属性 * 来表示它在字符串中:

# 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)" }
e0bqpujr

e0bqpujr2#

[string[]]$l_array = $l_table | out-string -stream
cwdobuhd

cwdobuhd3#

哈希只是一个Hashtable,因此它有一个keys和一个values属性。

$hash = @{}

$hash["foo"] = "bob"

$hash.Values

$hash.Values | Out-string

如果你想得到枚举数,它会返回keyvaluepair

$hash.GetEnumerator() |%{$_ | out-string}
huwehgph

huwehgph4#

虽然最初的发帖者可能想要一个与Format-Table的输出相对应的字符串数组,但正如所提供的尝试和发帖者自己的答案/评论所暗示的那样,问题标题的措辞更典型地是希望将散列表本身转换为每个项目值的数组的人(如果还不是String,则转换为String).对于那些寻找解决这个问题的方法的人,我提出以下方法(因为似乎还没有类似的问题):-
简单的答案是使用

[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](PSv 3+),项目的顺序未定义通常,当将散列表转换为数组时,期望具有该数组中的元素的特定排序。有时键是(正)整数,目的是使结果数组使用与数组索引相同的值(参见上面的$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
#

现在,结果数组将具有与适当索引值正确对应的整数键,方法是在数组中插入任何(未使用)数组项设置为“”如果这是一个问题,则可以使用两步过程来将“缺失”条目保留为$null。通过一次构建一个字典对的新哈希表,将非字符串哈希表转换为字符串,而不添加条目其次,在将哈希表(现在是字符串)转换为数组时,不要使用[string[]],以便将$null保留在“未使用”项中,如下所示

($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]]

将工作,但如果需要,使用[string[]]会将任何缺失的条目从$null更改为""

mm9b1k5b

mm9b1k5b5#

这是一个常见的问题;哈希表必须通过键或值来检索,但您无法获得对的集合-这就是原始哈希表。在我的示例中,哈希表由“字典”表示(您将记住VBS:-)。然而,您需要确定分隔键和值的分隔符,在本例中为“<->键值”。

$ARRAY = ( $DICT.Keys | foreach-object { "$_<->$($DICT[$_])"})

如果你愿意的话,你甚至可以先对键进行排序。在这个例子中,我反转到了Value<--->Key并按值进行排序。我还扩展了一点字符串,使其更详细但更清晰:

$ARRAY = ( $DICT.Keys | foreach-object { $DICT[$_] + "<--->" + $_} | sort-object)

相关问题