private/ConvertFrom-NexposeTable.ps1

Function ConvertFrom-NexposeTable {
<#
    .SYNOPSIS
        Convert a system command result table to into a PowerShell object

    .DESCRIPTION
        Convert a system command result table to into a PowerShell object

    .PARAMETER InputTable
        Output from system command containing a text drawn table

    .EXAMPLE
        ConvertFrom-NexposeTable -InputTable $commandResult

    .NOTES
        For additional information please see my GitHub wiki page

    .FUNCTIONALITY
        None

    .LINK
        https://github.com/My-Random-Thoughts/Rapid7Nexpose
#>


    Param (
        [string]$InputTable
    )

    Begin {
        [int]     $lineCnt = 0
        [object[]]$result  = @()
        [string[]]$headers = @()

        [long]    $refLng  = New-Object -TypeName 'Long'
        [double]  $refDbl  = New-Object -TypeName 'Double'
        [datetime]$refDtm  = New-Object -TypeName 'DateTime'
        [timespan]$refSpn  = New-Object -TypeName 'TimeSpan'

        [type]  $selectedType  = 'string'
        [string]$timeSpanRegex = '^(\d+)h(\d+)m(\d+)s$'
        [string]$dateTimeRegex = '^(\w{3})\s(\w{3})\s(\d{2})\s(\d\d:\d\d:\d\d)\sUTC\s(\d{4})$|^(\d{4}-)(\d{2}-)(\d{2}\s)(\d{2}:\d{2})() UTC$'
    }

    Process {
        ForEach ($line In ($InputTable -split '\r?\n')) {
            [boolean]$lineContinuation = $false
            If ([string]::IsNullOrEmpty($line)) { Continue }
            If (($line.StartsWith('+---')) -or ($line.StartsWith('|---'))) { $lineCnt++; Continue }

            [string[]]$data = ($line.Trim().Trim('|') -split '\|').Trim()

            If ($lineCnt -eq 1) { $headers = $data -replace '\s','' }
            if ($lineCnt -gt 1) {
                $object = [pscustomobject]@{}
                [int]$isBlank   = 0
                [int]$columnCnt = 0
                [boolean]$lineContinuation = $false

                # Check for line continuation
                ForEach ($item In $data) {
                    If ([string]::IsNullOrEmpty($item)) { $isBlank++; }
                }
                If (($isBlank -gt 0) -and ($isBlank -eq $data.Count -1)) { $lineContinuation = $true }

                ForEach ($item In $data) {
                    If ($item.Trim() -match $dateTimeRegex) {
                        $item = $item.Trim() -replace $dateTimeRegex, '$1 $2 $3 $5 $4 $6$7$8$9'
                        $selectedType = 'datetime'
                    }
                    ElseIf ($item -match $timeSpanRegex) {
                        $item = (New-TimeSpan -Hours $matches.1 -Minutes $matches.2 -Seconds $matches.3)
                        $selectedType = 'timespan'
                    }
                    ElseIf (($item.StartsWith('[')) -and (($item.EndsWith(']')))) {
                        $item = @($item.TrimStart('[').TrimEnd(']').Split(',').Trim())
                        $selectedType = 'string[]'
                    }
                    ElseIf (    [long]::TryParse($item, [ref]$refLng)) { $selectedType = 'long'     }
                    ElseIf (  [double]::TryParse($item, [ref]$refDbl)) { $selectedType = 'double'   }
                    ElseIf ([datetime]::TryParse($item, [ref]$refDtm)) { $selectedType = 'datetime' }
                    ElseIf ([timespan]::TryParse($item, [ref]$refSpn)) { $selectedType = 'timespan' }
                    Else                                               { $selectedType = 'string'   }    # Default fallback option

                    If ($lineContinuation -eq $false) {
                        Add-Member -InputObject $object -MemberType NoteProperty -Name $headers[$columnCnt] -Value ($item -as $selectedType)
                    }
                    Else {
                        If (-not [string]::IsNullOrEmpty($item.Trim())) {
                            $result[-1].$($headers[$columnCnt]) += " $item"
                        }
                    }

                    $columnCnt++
                }

                If ($lineContinuation -eq $false) { $result += $object }
            }
        }

        Return $result
    }

    End {
    }
}