Just a Bunch of Text Files

I wanted to share a quick hint about a cmdlet, ConvertFrom-StringData, I had the opportunity to put to use recently. ConvertFrom-StringData has been around since version 2.0 I believe but I wasn’t able to confirm that. What it basically does is take a string input and convert any key value pairs (“this = something”) it finds and converts them to a hashtable (i.e. object) that is familiar and consumable by everything PowerShell.

I spend a lot of my time at work integrating, consuming, and otherwise finagling something that doesn’t know about PowerShell and making it work with PowerShell. Until recently I had a lot of code that imported various sundry content with Get-Content then mashed it with various permutations of Select-String or regexp of some variety just to get an object that I could run with. That is the case no more.

For example a file (called “something.conf”) with the following content:

# This is a comment
URL=http://example.com
HOST=s.example.com
USER=bob smith
# More comments
FILE=somewhere.txt

Could be imported into a PowerShell hashtable as follows:

ConvertFrom-StringData -StringData (Get-Content -Raw -Path .\something.conf)

Will get you the following:

Name    Value
----    -----
HOST    s.example.com
FILE    somewhere.txt
USER    bob smith
URL     http://example.com

Which is a nice pretty hashtable. It even was smart enough to exclude the lines with comments (“#”). There are a couple of caveats here. If the file you are ingesting uses a comment character other than “#” (say “;”) then you would still have to do some manipulation before ingesting that string with the cmdlet. However ConvertFrom-StringData has cut out and certainly streamlined some of my mashing code. It is always nice to remove regexp stuff with a simple one-liner cmdlet.

In the command above I made sure to use the -Raw switch (new with version 3.0) on Get-Content which just reads the content in as one big string instead of a line by line array. This is helpful otherwise you get an array of hashtables with a key value pair each instead of an single hashtable with all keys and values. It could still work for you without the -raw parameter. Just keep in mind if you try to index the resulting array of hashtables you could make some false assumptions as the comments will occupy “empty” indexes within the array. So in the example above index 0 and 4 would be empty and would not include the contents of “URL” and “FILE” as you might expect.

It goes to show that you should always be looking at the various cmdlets, new and old, that come with PowerShell. You may find something that you can use to your advantage that will save you some labor. Unfortunately the help for ConvertFrom-StringData does not provide a “Get-Content” example which seems like an obvious one to me. Most of the examples use here strings which seem much more contrived. Why would you put that data into a here string only to convert it to a hash table, why not just build a hash table to begin with? Maybe there is a common pattern out there I just haven’t run across yet.

Either way ConvertFrom-StringData has been a real productivity boost for me now that I understand a couple of its gotchas. I can now parse my office compatriots Linux data better, faster, and stronger then they can, ha!

About these ads

2 responses to “Just a Bunch of Text Files

  1. Have you found an equally easy way to write back out to the properties file?

    I ended up writing a function, but was still hopeful that there is a better way.

    function Set-JavaPropertyFileValue($propFile, $propName, $propValue){

    [string]$finalFile=””

    if (test-path $propFile){
    write-verbose “Found property file $propFile”
    write-verbose “Read propfile”
    $file = gc $propfile

    foreach($line in $file){
    if ((!($line.StartsWith(‘#’))) -and
    (!($line.StartsWith(‘;’))) -and
    (!($line.StartsWith(“;”))) -and
    (!($line.StartsWith(‘`’))) -and
    (($line.Contains(‘=’)))){

    write-verbose “Searching for: $propName”
    $property=$line.split(‘=’)[0]
    write-verbose “Looking: $property”
    #split line, left side if propName right side is value

    if ($propName -eq $property){
    write-verbose “found property name”
    $line=”$propName=$propValue”
    }
    }
    $finalFile+=”$line`n”
    }

    $finalFile | out-file “$propFile” -encoding “ASCII”

    }else
    {
    write-error “Java Property file: $propFile not found”
    }
    }

  2. I haven’t specifically build a corollary to what I detail in the post. But it looks like your onto the right path.

    The one thing that I have done similarly before was use a Here string “template” that I filled variables with and then output. So it went something like:

    $Path = “D:\Temp”
    $FrgdColor = “Green”
    $BkgdColor = “Black”

    $ConfTemplate=@”
    # Some Random conf file somewhere
    Home=C:\Users\Joel
    Path=$($Path)
    ForegroundColor=$($FrgdColor)
    BackgroundColor=$($BkgdColor)
    “@
    $ConfTemplate | Out-File -Path ‘D:\Temp\New.conf’

    The key piece being the double quoted here-string that will then expand in the variables creating a string blob with all the bits. This method may or may not work depending on the complexity and variability of your conf file. I’ve use this method a couple times. I usually just embed the here-string in a function and then parametrize it to get me the blob I wanted.

    Good luck!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s