Search code examples
powershellcsvobject

How to convert CSV or Object-Array to an object but with the first column as properties


I want to store various outputs from Invoke-SSHCommands as objects.

Let's say i get the result formatted as CSV and i want to convert it to PSObject but the difficulty for me is that:

  1. Not the header but the first column should be interpreted as property names.
  2. The header names are always different.

The output from ssh looks like this but the header and values can differ depending of the ssh command:

PS> $mySSHResult

attribute            |value
---------------------+-----
hostname             |foo
version              |1.1
variant_id           |bar

I allready have converted the output to an Object[] with ConvertFrom-CSV but that's not practical for me. It looks like this:

PS> $mySSHResult | ForEach-Object {$_ -replace '\s*\|\s*', '|'} | ConvertFrom-Csv -Delimiter "|" | select -Skip 1

attribute    value
---------    -----
hostname     foo
version      1.1
variant_id   bar

What i want is the value of the first column as property name of the object. It should look like this:

PS> $myObject

hostname   version    variant_id
--------   -------    ----------
foo        1.1        bar

I tried my best with foreach() and | foreach-object but i'm to dumb too figure it out. Can somebody help me?


Solution

  • You could use ConvertFrom-StringData here, if you manage to replace pipes | with an = that could work. You will also need to skip the first 3 or 2 lines (unclear), so the headers.

    Assuming you have the sample:

    $mySSHResult = @'
    
    attribute            |value
    ---------------------+-----
    hostname             |foo
    version              |1.1
    variant_id           |bar
    '@ -split '\r?\n'
    

    Here you would use skip 3, since the output starts with a blank line, then for every line you can replace the | with an = and from there you convert all the lines into a single string with Out-String, this is so ConvertFrom-StringData outputs a single hashtable instead of an array of hashtables and lastly you can convert it to a psobject:

    $data = $mySSHResult |
        Select-Object -Skip 3 |
        ForEach-Object { $_.Replace('|', '=') } |
        Out-String |
        ConvertFrom-StringData
    
    [pscustomobject] $data
    

    Another option can be via split by | and trim the white space then populate an ordered dictionary and lastly convert it to a psobject:

    $data = [ordered]@{}
    $mySSHResult |
        Select-Object -Skip 3 |
        ForEach-Object {
            $key, $value = $_.Split('|').Trim()
            $data[$key] = $value
        }
    
    [pscustomobject] $data