I wasted almost two hours on this today. The goal was simply to create a function to pull out a 5 digit zip code from a string.

Three Powershell lessons learned :

1) using -match will return an additional $true/$false from a function unless you “swallow” the value into a variable.  http://stackoverflow.com/questions/27193956/extracting-data-from-the-matches-hashtable-after-a-powershell-regeg-match

2) return doesn’t necessarily do what you think it does http://stackoverflow.com/questions/10286164/powershell-function-return-value

3) the $Matches is just a hash table, but if you want to do Get_Item on it, do not enclose the 0 (zero) with quotes, because it is an integer not a string, and there is a difference between the two.

4) do not add .value on the hashtable, for example. $Matches[0] works, but $matches[0].Value does not.

My original problem:

Function GetZipCodeFromKeyword([String] $keyword)
{
   $pattern = "\d{5}"
   $keyword -match $pattern 
   #$isMatch = $keyword -match $pattern 
   $returnZipcode = "ERROR" 
   #Write-Host "GetZipCodeFromKeyword RegEx `$Matches.Count=$($Matches.Count)" 
   if ($Matches.Count -gt 0) 
      {
         $returnZipcode = $Matches[0] 
      }
   
   Write-Host "`$returnZipcode=$returnZipcode"
   return $returnZipcode 
}

Returned this result:

$returnZipcode=77562
Zip='True 77562' from keyword=Somewhere in 77562 Texas 
 
$returnZipcode=12345
Zip='False 12345' from keyword=Somewhere in Dallas Texas 

The fix was to change this line, from: 
$returnZipcode=77562
Zip='True 77562' from keyword=Somewhere in 77562 Texas 
 
$returnZipcode=12345
 $keyword -match $pattern 
to 
 $isMatch = $keyword -match $pattern 

This basically captures what would normally be output and returned, and puts the $true/$false into a variable.
I could then use that variable instead of looking at the .Count -gt 0.

When having that problem, I took my code out of the function to test and got hung-up on the hash table.
I was thinking the solution to my problem had to be using $Matches.Value[0] instead of just $Matche

This little test program will help illustrate how the $Matches collection works and doesn’t work:

   cls 
   $keyword = "this is a 12345 test" 
   $pattern = "\d{5}"
   $keyword -match $pattern 
   $returnZipcode = "ERROR" 
   Write-Host "GetZipCodeFromKeyword RegEx `$Matches.Count=$($Matches.Count)" 
   # Did this to show that it really a HashTable(System.Collections.DictionaryEntry)
   Write-Host $Matches   
   # Here is the way to dump out the contents of the Hash-Table 
   $Matches | Out-String | Write-Host
   Write-Host "`$Matches[0]=$($Matches[0])"
   Write-Host "`$Matches[0].Value=$($Matches[0].Value)"
   Write-Host "`$Matches.Get_Item(0)=$($Matches.Get_Item(0))"
   Write-Host "`$Matches.Get_Item('0')=$($Matches.Get_Item('0'))"
   if ($Matches.Count -gt 0) 
      {
         $returnZipcode = $Matches[0]
      }
   
   # this is how hash tables work - why doesn't same work with the $Matches variable? 
   $states = @{"Washington" = "Olympia"; "Oregon" = "Salem"; California = "Sacramento"}
   $states | Out-String | Write-Host
   Write-Host "`$states.Get_Item('Oregon')=$($states.Get_Item("Oregon"))"

Results:

True
GetZipCodeFromKeyword RegEx $Matches.Count=1
System.Collections.DictionaryEntry

Name                           Value                                                                          
----                           -----                                                                          
0                              12345                                                                          



$Matches[0]12345
$Matches[0].Value=
$Matches.Get_Item(0)=12345
$Matches.Get_Item('0')=

Name                           Value                                                                          
----                           -----                                                                          
Washington                     Olympia                                                                        
Oregon                         Salem                                                                          
California                     Sacramento                                                                     



$states.Get_Item('Oregon')=Salem

Note which combinations actually returned the desired value of “12345”.

Filed under: Uncategorized