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”.