Search code examples
powershellformattabular

Format table from output of a string


I have tried different ways but not able to format data into table

$str1 = "First string"
$str2 = "Sec string"
$str3 = "third str"
$str4 = "fourth string"

$str = "$str1 $str2 `r`n"
$str+= "$str3 $str4"

write-host $str | Format-Table

I am looking to create output like below:

First string  Sec string 
third str     fourth string

Solution

  • In order to use Format-Table as intended, you need objects with properties rather than mere strings:

    $str -split "`r`n" | ForEach-Object {
        # Initialize a custom object whose properties will reflect 
        # the input line's tokens (column values).
        $obj = New-Object PSCustomObject; $i = 0
        # Add each whitespace-separated token as a property.
        foreach ($token in -split $_) {
          Add-Member -InputObject $obj -NotePropertyName ('col' + ++$i) -NotePropertyValue $token
        }
        # Output the custom object.
        $obj
      } | Format-Table -HideTableHeaders
    
    • $str -split "`r`n" splits the multi-line string into individual lines and sends them through the pipeline one by one.

    • The ForEach-Object command constructs a custom object from each line whose properties are the whitespace-separated tokens on the line, as described in the comments; the property names - which don't matter for the output - are auto-generated as col1, col2, ...

      • Note: This does not match your desired output exactly in that each space (run of whitespace) is treated as a separator. If you wanted to treat the original $str1, $str2, ... variable values (e.g., First string) each as a single column value, you'd have to make assumptions about how to tokenize the line.
        For instance, if the assumption is that 2 consecutive words form a single value, replace -split $_ above with $_ -split '(\w+ \w+) ?' -ne ''

      • If you didn't want to rely on assumptions, you'd have to construct your input strings with embedded quoting so as to unambiguously indicate token boundaries (the code would then have to be modified to parse the embedded quoting correctly).

    • Format-Table then displays the custom objects in tabular form, with columns properly aligned; -HideTableHeaders suppresses the header line (the auto-generated property names).

    With your sample input, the above yields the following, produced without -HideTableHeaders so as to better illustrate what the code does:

    col1  col2   col3   col4
    ----  ----   ----   ----
    First string Sec    string
    third str    fourth string
    

    Ditto, but with the 2-consecutive-words splitting logic:

    col1         col2
    ----         ----
    First string Sec string
    third str    fourth string
    

    As for what you tried:

    • Do not use Write-Host to produce data output: Write-Host output (by default) goes to the console and bypasses the pipeline, so that Format-Table receives no input and has no effect here.

    • That said, even if Format-Table did receive input (by using $str by itself, without Write-Host, i.e.: $str | Format-Table), it would have no (visible) effect on strings, which are always rendered as-is.