在Powershell中将哈希表的输出格式化为一行输出

14

在PowerShell中,是否可以格式化哈希表的输出以将所有值输出到一行?

例如:

我有一个名为$hashErr的哈希表,其中包含以下值:

 $hashErr = @{"server1" = "192.168.17.21";
              "server2" = "192.168.17.22";
              "server3" = "192.168.17.23"}

以下是写入日志的内容:
$hashErr.GetEnumerator() | Sort-Object Name | ForEach-Object {ForEach-Object {"{0}`t{1}" -f $_.Name,($_.Value -join ", ")} | Add-Content $log

这将导致以下内容被写入日志:
    Name                           Value
    ----                           -----
server2                        192.168.17.22
server1                        192.168.17.21
server3                        192.168.17.23

我的问题是,如何格式化这个哈希表,使输出都写在一行上,就像下面这样?
server2 192.168.17.22 | server1 192.168.17.21 | server3 192.168.17.23

可以通过循环遍历哈希表中的所有值并将它们放入数组中来实现,但肯定有一种更直接的方式吗?

你似乎多了一个 ForEach-Object { 或者少了一个 }(无论哪种更改代码都可以正常工作,但外部的 ForEach-Object 不是必需的)。 - Duncan
@Duncan,就此而言,我根本不觉得需要使用Foreach-Object循环。$hashErr.GetEnumerator() | Sort Name单独就可以产生他的清单输出。实际上,使用Foreach-Object循环/格式化字符串甚至不会写入列标题。user_invalid,这些标题是从哪里来的?你是事先手动添加到日志中的吗? - Adi Inbar
标题并非手动添加,它们似乎是哈希表的标准输出,按照添加项目的顺序排列,例如:PS M:\> $hashErr - user_invalid
5个回答

12
你可以遍历哈希表的键,然后在循环中查找值。通过使用管道,您无需中间集合:
($hashErr.Keys | foreach { "$_ $($hashErr[$_])" }) -join "|"

6
理查德方案的V4版本:
$hashErr = @{"server1" = "192.168.17.21";
              "server2" = "192.168.17.22";
              "server3" = "192.168.17.23"}

$hashErr.Keys.ForEach({"$_ $($hashErr.$_)"}) -join ' | '

server3 192.168.17.23 | server2 192.168.17.22 | server1 192.168.17.21

4

虽然不是您想要的精确输出,但仍将输出在1行。

$hashErr | ConvertTo-Json -Compress

输出:

{"server2":"192.168.17.22","server3":"192.168.17.23","server1":"192.168.17.21"}

2
有点晚了,扩展一下@mjolinor的解决方案,您可以使用类型加速器[ordered]:
$hashErr = [ordered]@{"server1" = "192.168.17.21";
          "server2" = "192.168.17.22";
          "server3" = "192.168.17.23"}

$hashErr.Keys.ForEach({"$_ $($hashErr.$_)"}) -join ' | '

server1 192.168.17.21 | server2 192.168.17.22 | server3 192.168.17.23

我认为 [ordered] 是在 PS v. 3.0 中引入的。


1

您是否希望保留排序和单个服务器上多个IP地址的支持,这两者在您展示的代码中都存在但不在输出中?

如果是这样,我想最好的做法就是对原始代码进行轻微修改:

C:\scripts> ($hashErr.GetEnumerator() | sort Name | % { "$($_.Name) $($_.Value -join ',')" }) -join "|"
server1 192.168.17.21|server2 192.168.17.22|server3 192.168.17.23,1.2.3.4

顺序并不重要,但我希望每个键都有多个值的可能性。无论如何,这很完美地解决了我的问题,正是我所需要的。感谢您的帮助。 - user_invalid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接