Quick tip: $Matches is enough!

It does not happen very often: two posts in two days. But hey – if I have something (IMO) worth sharing, why wait? Puszczam oczko

Today I got question about parsing text file and while working on a solution I got idea how one can easily leverage named captures to create custom object on-the-fly.

Let us take WindowsUpdate.log as show case. At first I created pattern and generated v2 custom object (read: with all properties mixed up by the fact that hashtable does not care about order of keys). Than I took it to the next level that is fine as long as pattern is free of some regex syntax elements. To the point, raw objects in single step:

$Pattern = @(            
    '(?<Date>[\d-]+)'            
    '(?<Time>[\d:]+)'            
    '(?<Pid>\w+)'            
    '(?<Tid>\w+)'            
    '(?<Component>\w+)'            
    '(?<Text>.*)$'            
) -join '\s+'            
            
Get-Content C:\Windows\WindowsUpdate.log |             
    ForEach-Object {            
        if ($_ -match $Pattern) {            
            # We need to remove $Matches[0]            
            # Element always present in $Matches...            
            $Matches.Remove(0)            
            # All what left is named keys.. 🙂            
            New-Object PSObject -Property $Matches            
        }            
    } | select -First 10            

$Matches does it’s job, because all names of captures will appear as keys and related values will be equal to part of string that was captured. We only had to remove whole string stored in key 0. So far so good, but what if we want to have it ordered (both in v2 and v3)? We could simply add select at the end, but let’s play a bit more with $Pattern and make it more “juicy” from coding perspective:

$Names = 'Date', 'Time', 'Component', 'Pid', 'Tid', 'Text'            
            
$Pattern = (            
    @(            
        '(?<{0}>[\d-]+)'            
        '(?<{1}>[\d:]+)'            
        '(?<{3}>\w+)'            
        '(?<{4}>\w+)'            
        '(?<{2}>\w+)'            
        '(?<{5}>.*)$'            
    ) -join '\s+'            
) -f $Names

$Names contains array of strings we can use with select to get correct order. $Names decides on order of properties (used with select’s parameter –Property) and it does not have to match order of elements in pattern (as you can see in example: component is 5th in WindowsUpdate.log line, but 3rd property in resulting object).

Word of warning: it will break pattern if you have {n} in it (e.g. 4 digits translated into regex: \d{4}). In such a case just go with simple pattern and select properties in order you want. Puszczam oczko

Advertisement

1 thought on “Quick tip: $Matches is enough!

  1. Pingback: $Matches is enough! | psjjw

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 )

Facebook photo

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

Connecting to %s