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