5

I get the below output from a PowerShell query. I don't have access to the server to run the query, so I have no option to influence the output format.

Example:

Name          : folderC
FullName      : D:\folderA\folderB\folderC
Length        :
CreationTime  : 2/8/2014 11:12:58 AM
LastAccessTime: 2/8/2014 11:12:58 AM

Name          : filename.txt
FullName      : D:\folderA\folderB\filename.txt
Length        : 71560192
CreationTime  : 11/25/2015 3:10:43 PM
LastAccessTime: 11/25/2015 3:10:43 PM

How can I format above content to get something more usable, maybe like a table format like so:

Name|FullName|Length|CreationTime|LastAccessTime
1
  • 2
    Is the output objects or text? Pipe it through Get-Member (look for TypeName at the beginning of that output). Commented Jan 20, 2016 at 13:57

2 Answers 2

4

I think you need to split the text into records, replace the colons with equals so that you can use the ConvertFrom-StringData to turn each record into a hash which you can then feed into New-Object to convert into an object. Outputting the the object into pipe separated data can then be done with the ConvertTo-Csv. Something like so:

$x = @"
Name           : folderC
FullName       : D:\folderA\folderB\folderC
Length         : 0
CreationTime   : 2/8/2014 11:12:58 AM
LastAccessTime : 2/8/2014 11:12:58 AM

Name           : filename.txt
FullName       : D:\folderA\folderB\filename.txt
Length         : 71560192
CreationTime   : 11/25/2015 3:10:43 PM
LastAccessTime : 11/25/2015 3:10:43 PM
"@

($x -split '[\r\n]+(?=Name)') | % {
  $_ -replace '\s+:\s+', '='
} | % {
  $_ | ConvertFrom-StringData
} | % {
  New-Object psobject -Property $_
}  | ConvertTo-Csv -Delimiter '|' -NoTypeInformation
Sign up to request clarification or add additional context in comments.

3 Comments

Kudos for the clever block-splitting approach and ConvertFrom-StringData / New-Object combo; the only problem is that ConvertFrom-StringData interprets unquoted \ sequences as control-character escapes. Doubling the \ instances in the input should fix that ($_ -replace '\s+:\s+', '=') -replace '\\', '\\'
@mklement0 good point, probably needs a bit more testing with a larger data set. I think there maybe an issue when them is no value too. Maybe turning the strings into quoted strings might be the way to go. Make the replace: $_ -replace '\s+:\s+', "'='" and add another $_ -replace '^|$', "'"
Good point re empty values - they indeed cause problems. Quoting does not help, unfortunately - ConvertFrom-StringData retains them as literals.
3

As @alroc notes in a comment on the question, it is possible that objects are available to the OP, given that they state that the output is "from a Powershell query" - if so, simple reformatting of the object array using the usual cmdlets is an option.
By contrast, this answer assumes that only a text representation, as printed in the question, is available.

Dave Sexton's answer is a simpler and more elegant choice, if:

  • the input has no empty values (the OP's sample input does).
  • the input file is small enough to be read into memory as a whole.

Consider the approach below to avoid the issues above and/or if you want more control over how the input is converted into custom objects, notably with respect to creating properties with types other than [string]: extend the toObj() function below (as written, all properties are also just strings).


Get-Content File | % `
  -begin {
    function toObj([string[]] $lines) {
      $keysAndValues = $lines -split '(?<=^[^ :]+)\s*: '
      $htProps = @{}
      for ($i = 0; $i -lt $keysAndValues.Count; $i += 2) {
        $htProps.($keysAndValues[$i]) = $keysAndValues[$i+1]
      }
      return [PSCustomObject] $htProps
    }
    $lines = @()
  } `
  -process {
    if ($_.trim() -ne '') { 
      $lines += $_
    } else {
      if ($lines) { toObj $lines }
      $lines = @()
    }
  } `
  -end {
    if ($lines) { toObj $lines }
  } | Format-Table

Explanation:

  • Uses ForEach-Object (%) with separate begin, process, and end blocks.

  • The -begin, executed once at the beginning:

    • Defines helper function toObj() that converts a block of contiguous nonempty input lines to a single custom object.

      • toObj() splits an array of lines into an array of contiguous key-value elements, converts that array to a hashtable, which is then converted to a custom object.
    • Initializes array $lines, which will store the lines of a single block of contiguous nonempty input lines

  • The -process block, executed for each input line:

    • If the input line at hand is nonempty: Adds it to the current block of contiguous nonempty input lines stored in array $lines.

    • Otherwise: Submits the current block to toObj() for conversion to a custom object, and then resets the $lines array to start the next block. In effect, toObj() is invoked for each paragraph (run of nonempty lines).

  • The -end block, executed once at the end:

    • Submits the last paragraph to toObj() for conversion to a custom object.
  • Finally, the resulting array of custom objects is passed to Format-Table.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.