Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Convert Text to Object

Posted on October 25, 2011September 13, 2013

Today I have another tool in my new battle regarding turning command line tools into PowerShell tools. The bottom line is we want to have objects written to the pipeline. At the PowerShell Deep Dive in Frankfurt there was a suggestion about providing tools to help with the transformation from CLI to PowerShell and this is one of the items I came up with.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

Many command line tools write output in a structured format. For example run this command:

C:\> tasklist /fo list

There's an "object" staring at us for each task. As an aside, don't focus on the command line tool I'm using, pay attention to the technique. To turn output like this into ah object we simply need to split each line at the colon. The first index of the array will be the "property" name and the second index is the value. Here's the function I pulled together.

Function Convert-TextToObject {

<#
This function takes a collection of simple delimited lines and
turns them into an object. The function assumes a single delimiter.
The default delimiter is the colon (:). The item to the left will be
the property and the item on the left will be the property value.

Use $GroupCount to keep track of items that come in groups and write a new object
when the count has been reached. For example, this allows you to pipe
in a long collection of strings and turn every 5 into an object.

tasklist /s server01 /fo list | where {$_} | convert-texttoobject -group 5
#>

[cmdletbinding(SupportsShouldProcess=$True)]

param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a string to be parsed into an object",
ValueFromPipeline=$True)]
[ValidateNotNullorEmpty()]
[string[]]$Text,
[string]$Delimiter=":",
[int]$GroupCount
)

Begin {
Write-Verbose "Starting $($myinvocation.mycommand)"
#define a hashtable
$myHash=@{}
if ($GroupCount) {
Write-Verbose "Grouping every $GroupCount items as an object"
}
#start an internal counter
$i=0
}

Process {

Foreach ($item in $text) {

if ($i -lt $GroupCount) {
$i++
}
else {
#reset
$i=1
}

#split each line at the delimiter
$data=$item.Split($delimiter)
#remove spaces from "property" name
$prop=$data[0].Replace(" ","")

#trim
$prop=$prop.Trim()
$val=$data[1].Trim()

#add to hash table
Write-Verbose "Adding $prop to hash table with a value of $val"
$myHash.Add($prop,$val)

#if internal counter is equal to the group count
#write the object and reset the hash table
if ($i -eq $groupCount) {
New-Object -TypeName PSObject -Property $myHash
$myHash.Clear()
}

} #foreach
}
End {
#create new object from hash table
if ($myHash.count -gt 0) {
New-Object -TypeName PSObject -Property $myHash
Write-Verbose "Ending $($myinvocation.mycommand)"
}
}

} #end function

The function processes each incoming line of text and splits it on the delimiter. The default is the colon since many CLI tools seem to use it.

#split each line at the delimiter
$data=$item.Split($delimiter)

Since I prefer property names without spaces I remove them from index 0 of the array. I've also found it helpful to trim everything to eliminate extra white space.

#remove spaces from "property" name
$prop=$data[0].Replace(" ","")

#trim
$prop=$prop.Trim()
$val=$data[1].Trim()

Each line is then added to a hash table.

#add to hash table
Write-Verbose "Adding $prop to hash table with a value of $val"
$myHash.Add($prop,$val)

When the hash table is complete it is used to create a new object.

New-Object -TypeName PSObject -Property $myHash

The other "trick" I added is to group lines into an object. This let's me take say every 5 lines of text and make that a single object. I create a counter and increment it whenever a line is processed. When the counter meets the limit, the object is created, the hash table is cleared and the process repeats.

#if internal counter is equal to the group count
#write the object and reset the hash table
if ($i -eq $groupCount) {
New-Object -TypeName PSObject -Property $myHash
$myHash.Clear()
}

Now I can run a command like this:

PS D:\scripts> tasklist /fo list | where {$_} | Convert-TextToObject -group 5

Session# : 0
SessionName : Services
PID : 0
MemUsage : 24 K
ImageName : System Idle Process

Session# : 0
SessionName : Services
PID : 4
MemUsage : 96 K
ImageName : System

Session# : 0
SessionName : Services
PID : 412
MemUsage : 1,164 K
ImageName : smss.exe
...

The output looks similar but now I have objects so I can take advantage of PowerShell. Here are some examples:

tasklist /fo list | where {$_} | Convert-TextToObject -group 5 | ft -auto
tasklist /fo list | where {$_} | Convert-TextToObject -group 5 | group SessionName
tasklist /s $computer /fo list | where {$_} | Convert-TextToObject -GroupCount 5 | Add-member not
eproperty Computername $computer -pass | Export-CSV taskreport.csv

This is by no means perfect but I'd like to think it is a good start. For example, one downside is that all properties are strings where it would be nicer to have properties of an appropriate type. Still, I hope you'll try this out and let me know what you think.

Download Convert-TexttoObject

Update
A newer version of the script can be found at https://jdhitsolutions.com/blog/2012/01/convert-text-to-object-updated/


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

9 thoughts on “Convert Text to Object”

  1. Neil says:
    October 25, 2011 at 11:25 am

    Just what I was looking for! Thanks though I had to remove the whitespace between
    “[cmdletbinding(SupportsShouldProcess=$True)]” and the ” param (” lines to get this to run. But I’m not sure why as I thought that powershell just ignored the whitespace formating. Any suggestions to what I’m missing?

    1. Jeffery Hicks says:
      October 25, 2011 at 11:32 am

      Am glad this works for you. Although I’m not sure why you would need to make those edits. Unless there’s some weird artifact from encoding, uploading or downloading.

      1. Jeffery Hicks says:
        October 25, 2011 at 11:36 am

        I downloaded the text file and it ran just fine for me. Perhaps you got an extra odd character on your download.

  2. Will Steele says:
    October 25, 2011 at 12:13 pm

    Where was this yesterday when I needed it? : ) Thanks for the post. Appreciate the more universalized approach than the one I hacked up.

    1. Jeffery Hicks says:
      October 25, 2011 at 12:17 pm

      That always seem to be the case: you find exactly what you need when you no longer need it. Thanks for the feedback.

  3. Ajensen says:
    November 3, 2011 at 2:27 pm

    Hi,

    thanks for your endless support to the community.

    I use this script for deleting old files from 7zip archives.
    The 7z.exe utility adds a few lines in the start of the output so I added a -SkipLines parameter that skips the necessary number of lines.

    ...
    [int]$SkipLines,
    ...
    Process {
    Foreach ($item in $text) {
    if ($SkipLines -gt 0 -and $i -le $SkipLines){
    $i++
    if($i -eq $SkipLines){$i=0; $SkipLines=0}
    }
    else {
    if ($i -lt $GroupCount) {
    ...

    1. Jeffery Hicks says:
      November 3, 2011 at 2:31 pm

      Great! That’s exactly the type of approach I’m talking about. Thanks for the feedback.

  4. Thomas says:
    January 10, 2012 at 6:52 pm

    Ran across this via the Powershell podcast. I’m parsing Netapp, Snapdrive report by batch file. Tried this script, but could not convert the WWPN line into an object. Is there a way to make the script just search for the first “:”.
    — Thanks
    eg.
    FCP initiator WWPN: 10:00:00:00:a1:2b:3c:4d

    1. Jeffery Hicks says:
      January 11, 2012 at 9:14 am

      You can try something like this:

      PS C:\> $s=”FCP initiator WWPN:10:00:00:00:a1:2b:3c:4d”
      PS C:\> $s.split(“:”,2)
      FCP initiator WWPN
      10:00:00:00:a1:2b:3c:4d

      I should add this option to my function.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d