Tag Archives: hashtable

Convert Text to Object with PowerShell and Regular Expressions

squarepatternA few weeks ago I was getting more familiar with named captures in regular expressions. With a named capture, you can give your matches meaningful names which makes it easier to access specific captures. The capture is done by prefixing your regular expression pattern with a name.

When you know the name, you can get the value from $matches.

This also works, and even a bit better, using a REGEX object.

With the REGEX object you can get the names.

Because the names include index numbers, I usually filter them out. Once I know the names, I can use them to extract the relevant matches.

Then I realized it wouldn’t take much to take this to the next step in PowerShell. I have a name and a value, why not create an object? It isn’t too difficult to create a hashtable on the fly and use that to create a custom object. Eventually I came up with ConvertFrom-Text.

The function requires a regular expression pattern that uses named captures. With the pattern you can either specify the path to a log file, or you can pipe structured text to the function. By “structured text” I mean something like a log file with a predictable pattern. Or even output from a command line tool that has a consistent layout. The important part is that you can come up with a regular expression pattern to analyze the data. I also wanted to be able to pipe in text in the event I only wanted to process part of a large log file.

Here’s an example using the ARP command.

In this particular example, I’m trimming the ARP output to remove any leading or trailing spaces from each line and then converting each line to an object, using the regular expression pattern.

convertfrom-text

If you haven’t jumped to why command is useful, is that once I have objects I can easily filter, sort, group, export, or just about anything else. By converting a log file into a collection of objects I can do tasks like this:

convertfrom-text-2

I hope some of you will try this out and let me know what you think. What works? What is missing? What problem did this solve? Inquiring minds, well at least mine, want to know. Enjoy.

Friday Fun: Out-ConditionalColor

Last week I posted a Friday Fun article on parsing results from Invoke-Webrequest and displaying matching strings in color so that the book titles I’m interested in stand out. But the more I thought about it I realized I should take this a step further. The problem with Write-Host is that it doesn’t write anything to the pipeline which is why we typically frown upon its use. Although being able to use color to highlight something is very cool. I wanted color and pipelined output. Here’s my result.

This function only really works in the PowerShell console. It is designed to accept any PowerShell input. The function also takes parameters that help it write matching objects in the specified color. The easy way to use the function is to specify a property and a hashtable. The hashtable key is the value you want to match in the input and the key is the color you want to use. The function processes each object as it comes in and if the property matches the value it sets the foreground color of the console to the specified value.

If it doesn’t match then the foreground color essentially remains the same. This means I can run a command like this:

And get a result like this:
occ-basic

Any time the process name is equal to ‘chrome’ I display that object in yellow. You can also have multiple entries.

occ-basic2
I mentioned match earlier but it is really a simple equality test. However, I also added code so that you could be even more granular.
You can also create what I refer to as a complex hashtable. This must be an ordered hashtable, which means you must be running PowerShell 3.0. Define a hashtable like this:

This is a little tricky. The key is actually scriptblock of the object property and some operator comparison. The key is the console color you want to use for the match. Use $psitem to represent the current object in the pipeline. The reason for the ordered hashtable is because the keys are processed in an If/ElseIf fashion so make sure you get things in the right order.

The function breaks apart the hashtable and builds a here string of the If/ElseIf structure in the Begin scriptblock.

The here string includes the commands to set the host foreground color. Then in the Process scriptblock I use Invoke-Expression to execute it.

But now I can do this.

occ-complex
When using a complex hashtable, there’s no need to specify a property. What’s great about all of this is that if you want to see the color output and still save the results, use the common -Outvariable parameter with Out-Conditionalcolor.

$P won’t be colorized (unless I run it through the function again), but I still have the data.

There are some limitations. Like any Out cmdlet, this must be the last command in your pipelined expression. Technically you could sort or filter after my function, but it will lose the conditional coloring. Unlike the other Out cmdlets, you cannot piped any formatted data to it.

The whole point of the function is to provide a means of adding some visual references to your PowerShell data.
occ-basic3

I sincerely hope you’ll try this out and let me know what you think.

Rename Hashtable Key Revised

Last week I posted an advanced PowerShell function to rename a hashtable key. As usual, the more I worked with it the more I realized it was missing something – namely the ability the take a pipelined object. My original version assumed you had saved the hashtable to a variable. But as I was working with ConvertTo-Hashtable I realized the shortcoming. The solution was to modify Rename-Hashtable so that it could accept a hashtable as a piped value.

I won’t go through the function again. You can read the original post to learn more about how it works. Let’s look at what changed. Because I wanted to retain the option to also specify a variable name, I created two parameters sets. One for the piped object and one for the variable name.


[cmdletbinding(SupportsShouldProcess=$True,DefaultParameterSetName="Pipeline")]

Param(
[parameter(Position=0,Mandatory=$True,
HelpMessage="Enter the name of your hash table variable without the `$",
ParameterSetName="Name")]
[ValidateNotNullorEmpty()]
[string]$Name,
[parameter(Position=0,Mandatory=$True,
ValueFromPipeline=$True,ParameterSetName="Pipeline")]
[ValidateNotNullorEmpty()]
[object]$InputObject,
[parameter(position=1,Mandatory=$True,
HelpMessage="Enter the existing key name you want to rename")]
[ValidateNotNullorEmpty()]
[string]$Key,
[parameter(position=2,Mandatory=$True,
HelpMessage="Enter the NEW key name")]
[ValidateNotNullorEmpty()]
[string]$NewKey,
[switch]$Passthru,
[ValidateSet("Global","Local","Script","Private",0,1,2,3)]
[ValidateNotNullOrEmpty()]
[string]$Scope="Global"
)

I defined parameter sets called Pipeline and Name and made the former the default in the cmdletbinding attribute. Because the remaining parameters would be in both parameter sets I didn’t specify one. When looking at the function’s help you can see the result.

rename-hashtable-paramsets

Because I’m taking input from the pipeline, I needed to add a Process scriptblock. Within the scriptblock, if an object has been piped in, I turn on the passthru variable and create a temporary copy of the piped in hashtable.


Process {
#validate Key and NewKey are not the same
if ($key -eq $NewKey) {
Write-Warning "The values you specified for -Key and -NewKey appear to be the same. Names are NOT case-sensitive"
Return
}

Try {
#validate variable is a hash table
if ($InputObject) {
$name="tmpInputHash"
Set-Variable -Name $name -Scope $scope -value $InputObject
$Passthru=$True
}
...

The rest of the code worked just fine and there was no reason to change it. All I needed to do was transform the -Inputobject value into the -Name value since I already had code that used $Name. Sometimes you need separate code blocks but in this case I didn’t. Once the transformation is complete, the rest of the function runs as originally designed. With this version I can now run commands like this:


PS C:\> $h = get-service spooler -computer Serenity | convertto-hashtable -NoEmpty -Exclude CanStop,CanPauseAndcontinue | rename-hashtable -key machinename -new computername
PS C:\> $h

Name Value
---- -----
computername Serenity
Name spooler
ServiceName spooler
RequiredServices {RPCSS, http}
DependentServices {Fax}
ServiceType Win32OwnProcess, InteractiveProcess
Status Running
ServicesDependedOn {RPCSS, http}
ServiceHandle SafeServiceHandle
DisplayName Print Spooler

Download Rename-Hashtable2 and give it a go.