Format the output of a hash table in Powershell to output to one line
Asked Answered
L

6

19

Is it possible to format the output of a hashtable in Powershell to output all the values onto one line?

e.g.

I have the hash table $hashErr with the below values:

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

Which are written to a log with the below:

$hashErr.GetEnumerator() | Sort-Object Name | ForEach-Object {ForEach-Object {"{0}`t{1}" -f $_.Name,($_.Value -join ", ")} | Add-Content $log

The will cause the below to be written to the log:

    Name                           Value
    ----                           -----
server2                        192.168.17.22
server1                        192.168.17.21
server3                        192.168.17.23

My question is, how can I format this hash table so the output is written all to one line, like the below?

server2 192.168.17.22 | server1 192.168.17.21 | server3 192.168.17.23

This could be done by looping through all the values in the hash table and putting them into an array but surely there is a more direct way?

Lefler answered 7/1, 2014 at 15:15 Comment(3)
You seem to either have an extra ForEach-Object { or a missing } (with either change the code works way but the outer ForEach-Object isn't needed).Pitchblack
@Pitchblack For that matter, I don't see the need for the Foreach-Object loop at all. $hashErr.GetEnumerator() | Sort Name by itself produces the output in his listing. In fact, doing it with the Foreach-Object loop/formatted strings wouldn't even write the column headings. user_invalid, where did those headings come from? Did you add them to the log manually beforehand?Resident
The headings weren't added manually, they seem to be a standard output of a hash table, in the order that the items were added, e.g. PS M:\> $hashErr Lefler
J
12

You can iterate over the keys of a hash table, and then in the loop lookup the values. By using the pipeline you don't need an intermediate collection:

($hashErr.Keys | foreach { "$_ $($hashErr[$_])" }) -join "|"
Josephjosepha answered 7/1, 2014 at 15:23 Comment(0)
C
10

Not excat output as you want but also 1 line output.

$hashErr | ConvertTo-Json -Compress

outputs:

{"server2":"192.168.17.22","server3":"192.168.17.23","server1":"192.168.17.21"}
Cancer answered 22/6, 2020 at 16:3 Comment(0)
V
6

The V4 version of Richard's solution:

$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
Vookles answered 7/1, 2014 at 20:47 Comment(0)
J
2

A bit late to the party, expanding on @mjolinor's solution, you can use the type accelerator [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

I think [ordered] was introduced in PS v. 3.0.

Jonette answered 4/10, 2016 at 0:56 Comment(0)
P
1

Do you want to keep the sorting, and support for multiple ip addresses on a single server, both of which are in the code you showed but not in your output?

If so I think the best you'll get is just a minor modification on the original:

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
Pitchblack answered 7/1, 2014 at 16:22 Comment(1)
Order isn't important but I would like to have the possibility of having multiple values per key. In any case this works perfectly and was exactly what I was looking for. Thanks for the help.Lefler
P
0

GetEnumerator allows to iterate over the Key-Value pairs. The resulting code looks looks alot cleaner and easier to understand.

($hashErr.GetEnumerator() | ForEach-Object{ "$($_.Key) $($_.Value)" }) -join " | "

server2 192.168.17.22 | server3 192.168.17.23 | server1 192.168.17.21
Phyte answered 27/1 at 20:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.