Search code examples
powershellpropertiesmultiple-columns

Extract columns from text based table output


qfarm /load command shows me the load from my servers. Output:

PS> qfarm /load

Server Name           Server Load  Load Throttling Load  Logon Mode
--------------------  -----------  --------------------  ------------------
SERVER-01             400          0                     AllowLogons
SERVER-02             1364         OFF                   AllowLogons
SERVER-03             1364         OFF                   AllowLogons
SERVER-04             1000         0                     AllowLogons
SERVER-05             700          0                     AllowLogons
SERVER-06             1200         0                     AllowLogons

I need to display only first column (Server Name) and the second one (Server Load) and loop through them, in order to make some logic later, but it seems the powershell doesn't see it as object with properties:

PS> qfarm /load | Select -ExpandProperty "Server Name"
Select-Object : Property "Server Name" cannot be found.

Is there any other possibility, like a table or something?


Solution

  • One way to do this is to build objects out of the command's output. Tested the following:

    #requires -version 3
    
    # sample data output from command
    $sampleData = @"
    Server Name           Server Load  Load Throttling Load  Logon Mode
    --------------------  -----------  --------------------  ------------------
    SERVER-01             400          0                     AllowLogons
    SERVER-02             1364         OFF                   AllowLogons
    SERVER-03             1364         OFF                   AllowLogons
    SERVER-04             1000         0                     AllowLogons
    SERVER-05             700          0                     AllowLogons
    SERVER-06             1200         0                     AllowLogons
    "@ -split "`n"
    
    $sampleData | Select-Object -Skip 2 | ForEach-Object {
      $len = $_.Length
      [PSCustomObject] @{
        "ServerName"         = $_.Substring(0,  22).Trim()
        "ServerLoad"         = $_.Substring(22, 13).Trim() -as [Int]
        "LoadThrottlingLoad" = $_.Substring(35, 22).Trim()
        "LogonMode"          = $_.Substring(57, $len - 57).Trim()
      }
    }
    

    In your case, you should be able to replace $sampleData with your qfarm load command; e.g.:

    qfarm /load | Select-Object -Skip 2 | ForEach-Object {
    ...
    

    Of course, this is assuming no blank lines in the output and that my column positions for the start of each item is correct.

    PowerShell version 2 equivalent:

    #requires -version 2
    
    function Out-Object {
      param(
        [Collections.Hashtable[]] $hashData
      )
      $order = @()
      $result = @{}
      $hashData | ForEach-Object {
        $order += ($_.Keys -as [Array])[0]
        $result += $_
      }
      New-Object PSObject -Property $result | Select-Object $order
    }
    
    # sample data output from command
    $sampleData = @"
    Server Name           Server Load  Load Throttling Load  Logon Mode
    --------------------  -----------  --------------------  ------------------
    SERVER-01             400          0                     AllowLogons
    SERVER-02             1364         OFF                   AllowLogons
    SERVER-03             1364         OFF                   AllowLogons
    SERVER-04             1000         0                     AllowLogons
    SERVER-05             700          0                     AllowLogons
    SERVER-06             1200         0                     AllowLogons
    "@ -split "`n"
    
    $sampleData | Select-Object -Skip 2 | ForEach-Object {
      $len = $_.Length
      Out-Object `
        @{"ServerName"         = $_.Substring(0,  22).Trim()},
        @{"ServerLoad"         = $_.Substring(22, 13).Trim() -as [Int]},
        @{"LoadThrottlingLoad" = $_.Substring(35, 22).Trim()},
        @{"LogonMode"          = $_.Substring(57, $len - 57).Trim()}
    }