Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell: match operator returns true but $matches is null

I am working with a regex to match file contents:

> (get-content $_) -match $somePattern
the line of text that matches the pattern

this returns true, a match, however my $matches variable remains null.

> $matches -eq $null
True

Shouldn't $matches have the match groups in it?

like image 466
Matthew Bonig Avatar asked Dec 28 '11 04:12

Matthew Bonig


2 Answers

Strictly speaking string -match ... and collection -match ... are two different operators. The first gets a Boolean value and fills $matches. The second gets each collection item that matches a pattern and apparently does not fill $matches.

Your example should work as you expect if the file contains a single line (the first operator works). If a file contains 2+ lines then the second operator is used and $matches is not set.

The same is true for other Boolean operators applied to a collection. That is collection -op ... returns items where item -op ... is true.

Examples:

1..10 -gt 5 # 6 7 8 9 10
'apple', 'banana', 'orange' -match 'e' # apple, orange 

Boolean operators applied to collections are handy if used properly. But they may be confusing as well and lead to easy to make mistakes:

$object = @(1, $null, 2, $null)

# "not safe" comparison with $null, perhaps a mistake
if ($object -eq $null) {
    '-eq gets @($null, $null) which is evaluated to $true by if!'
}

# safe comparison with $null
if ($null -eq $object) {
    'this is not called'
}

Another example with -match and -notmatch may look confusing:

$object = 'apple', 'banana', 'orange'

if ($object -match 'e') {
    'this is called'
}

if ($object -notmatch 'e') {
    'this is also called, because "banana" is evaluated to $true by if!'
}
like image 162
Roman Kuzmin Avatar answered Nov 13 '22 16:11

Roman Kuzmin


I had the same problem, and the exact lines were working from the Powershell command prompt but not from Powershell ISE or a normal command prompt. If you don' want to cycle through all the lines of the file one by one using foreach, you can simply convert that to a string like this and it should work then:

if([string](Get-Content -path $filePath) -match $pattern)
{
   $matches[1]
}
like image 24
Piyush Soni Avatar answered Nov 13 '22 17:11

Piyush Soni