Author Posts

June 10, 2016 at 10:48 pm

Hi All,
Happy Friday, no rush on this one.. 🙂

I've always had trouble understanding how to utilize regex matching in PS. Does the match return a boolean, or a string? Sometimes both depending on the time of day? ¯\_(ツ)_/¯

Here's a good example, I can pull text from a backup job property and try to grab the 3 different numbers from it for use in a report. There might be better ways of accomplishing this, but I really want to understand how this $matches variable should work.

$DSVerbiage = '
30 generations
If files are removed from source after 30 days, keep only 0 generations
online.
'

[string]$LiveItemGenerationsPattern = '(\d{1,8})\sgeneration[s]?\sIf' 
[int]$LiveItemGenerations = $DSVerbiage -match $LiveItemGenerationsPattern | %{$Matches.Values[0]}         # should be 30

[string]$DeletedItemRetentionPattern = '(\d{1,8})\sdays, keep'
[int]$DeletedItemRetention = $DSVerbiage -match $DeletedItemRetentionPattern | %{$Matches.Values[0]}       # should be 30

[string]$DeletedItemGenerationsPattern = 'only\s(\d{1,12})\sgeneration'
[int]$DeletedItemGenerations = $DSVerbiage -match $DeletedItemGenerationsPattern | %{$Matches.Values[0]}   # should be 0

# FYI- I used regex101.com to test the patterns

When I was building this, the first pattern returned 30, as it should have.

PS> $DSVerbiage -match $LiveItemGenerationsPattern | %{$Matches.Values[0]} 
30

Then I tried the second. It didn't work. Then I tried the first again, it no longer worked.

PS> $DSVerbiage -match $DeletedItemRetentionPattern | %{$Matches.Values[0]} 
PS> 
PS> $DSVerbiage -match $DeletedItemRetentionPattern | %{$Matches.Values[0]} 
30
30 days, keep
PS> $DSVerbiage -match $DeletedItemRetentionPattern 
True
PS> $DSVerbiage -match $LiveItemGenerationsPattern 
False
PS>

Weird right? I always see this when I play around with Regex, get frustrated, then find some other way to do it. Right now I'm thinking about getting into the backup application's DB to pull out the numbers directly. I also know that Regex is something that should be used when no other solution can get me to my goal, but I REALLY want to understand how these matches work.

Also FYI:

PS H:\> $PSVersionTable
Name Value
—- —–
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34209
BuildVersion 6.3.9600.16406
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2

June 11, 2016 at 6:40 am

Hey Tony,
There are many ways to do Regex in Powershell, but below I will try to help explain how the -match operator works

When you use -match, the operation returns a true or false Boolean value indicating whether the Regex pattern provided matched the string.

$DSVerbiage = '
30 generations
If files are removed from source after 30 days, keep only 0 generations
online.
'

$LiveItemGenerationsPattern = '(\d{1,8})\sgeneration[s]?\sIf'
$LiveItemGenerations = $DSVerbiage -match $LiveItemGenerationsPattern
$LiveItemGenerations

Results:

True

At the same time, the $matches automatic variable is populated with a hashtable containing the regex matches

Get-Member -InputObject $Matches
$Matches

Results:

   TypeName: System.Collections.Hashtable

Name              MemberType            Definition                                                                                                                                                                                                               
----              ----------            ----------                                                                                                                                                                                                               
Add               Method                void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, System.Object value)                                                                                                           
Clear             Method                void Clear(), void IDictionary.Clear()                                                                                                                                                                                   
Clone             Method                System.Object Clone(), System.Object ICloneable.Clone()                                                                                                                                                                  
Contains          Method                bool Contains(System.Object key), bool IDictionary.Contains(System.Object key)                                                                                                                                           
ContainsKey       Method                bool ContainsKey(System.Object key)                                                                                                                                                                                      
ContainsValue     Method                bool ContainsValue(System.Object value)                                                                                                                                                                                  
CopyTo            Method                void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array array, int index)                                                                                                                                
Equals            Method                bool Equals(System.Object obj)                                                                                                                                                                                           
GetEnumerator     Method                System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections.IDictionaryEnumerator IDictionary.GetEnumerator(), System.Collections.IEnumerator IEnumerable.GetEnumerator()                               
GetHashCode       Method                int GetHashCode()                                                                                                                                                                                                        
GetObjectData     Method                void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context), void ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, ...
GetType           Method                type GetType()                                                                                                                                                                                                           
OnDeserialization Method                void OnDeserialization(System.Object sender), void IDeserializationCallback.OnDeserialization(System.Object sender)                                                                                                      
Remove            Method                void Remove(System.Object key), void IDictionary.Remove(System.Object key)                                                                                                                                               
ToString          Method                string ToString()                                                                                                                                                                                                        
Item              ParameterizedProperty System.Object Item(System.Object key) {get;set;}                                                                                                                                                                         
Count             Property              int Count {get;}                                                                                                                                                                                                         
IsFixedSize       Property              bool IsFixedSize {get;}                                                                                                                                                                                                  
IsReadOnly        Property              bool IsReadOnly {get;}                                                                                                                                                                                                   
IsSynchronized    Property              bool IsSynchronized {get;}                                                                                                                                                                                               
Keys              Property              System.Collections.ICollection Keys {get;}                                                                                                                                                                               
SyncRoot          Property              System.Object SyncRoot {get;}                                                                                                                                                                                            
Values            Property              System.Collections.ICollection Values {get;}                                                                                                                                                                             

Key   : 1
Value : 30
Name  : 1


Key   : 0
Value : 30 generations
        If
Name  : 0

Likewise for your Second Pattern match

$DSVerbiage = '
30 generations
If files are removed from source after 30 days, keep only 0 generations
online.
'

$DeletedItemRetentionPattern = '(\d{1,8})\sdays, keep'
$DeletedItemRetention = $DSVerbiage -match $DeletedItemRetentionPattern

$DeletedItemRetention
$Matches

Results:

True

Name                           Value
----                           -----
1                              30
0                              30 days, keep

As well as your third pattern

$DSVerbiage = '
30 generations
If files are removed from source after 30 days, keep only 0 generations
online.
'
$DeletedItemGenerationsPattern = 'only\s(\d{1,12})\sgeneration'
$DeletedItemGenerations = $DSVerbiage -match $DeletedItemGenerationsPattern

$DeletedItemRetention
$Matches

Results:

True

Name                           Value
----                           -----
1                              0
                              only 0 generation

You should be able to see the pattern here. The value you are looking for is the second value in the resulting hashtable. So you can those values accordingly

$DSVerbiage = '
30 generations
If files are removed from source after 30 days, keep only 0 generations
online.
'

$LiveItemGenerationsPattern = '(\d{1,8})\sgeneration[s]?\sIf'
$LiveItemGenerations = $DSVerbiage -match $LiveItemGenerationsPattern

$Matches[1]

$DeletedItemRetentionPattern = '(\d{1,8})\sdays, keep'
$DeletedItemRetention = $DSVerbiage -match $DeletedItemRetentionPattern

$Matches[1]

$DeletedItemGenerationsPattern = 'only\s(\d{1,12})\sgeneration'
$DeletedItemGenerations = $DSVerbiage -match $DeletedItemGenerationsPattern

$Matches[1]

Results:

30
30
0

June 13, 2016 at 5:03 am

Yes! Thank you! The elusive hash table strikes again.