Matches not captured when using -SimpleMatch with

2019-09-09 21:44发布

问题:

I have been using regex to parse text within some XML nodes. However, when I use -SimpleMatch with Select-String, the MatchInfo object doesn't appear to contain any matches.

I am unable to find anything online that indicates this behavior is normal. I am now wondering if it is my Powershell installation. (For reference: the computer I'm using has Powershell 3.0 installed.)

Using a very simple example, we can return the expected MatchInfo Object when using the regex patterning:

PS H:\> $c = "abd 14e 568" | Select-String -Pattern "ab"

PS H:\> $c.Matches


Groups   : {ab}
Success  : True
Captures : {ab}
Index    : 0
Length   : 2
Value    : ab

But adding the -SimpleMatch parameter appears to not return the Matches property in the MatchInfo object:

PS H:\> $c = "abd 14e 568" | Select-String -Pattern "ab" -SimpleMatch

PS H:\> $c.Matches

PS H:\>

Piping $c to Get-Member confirms a MatchInfo Object was returned:

PS H:\> $c | gm


   TypeName: Microsoft.PowerShell.Commands.MatchInfo

Name         MemberType Definition                                                       
----         ---------- ----------                                                       
Equals       Method     bool Equals(System.Object obj)                                   
GetHashCode  Method     int GetHashCode()                                                
GetType      Method     type GetType()                                                   
RelativePath Method     string RelativePath(string directory)                            
ToString     Method     string ToString(), string ToString(string directory)             
Context      Property   Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename     Property   string Filename {get;}                                           
IgnoreCase   Property   bool IgnoreCase {get;set;}                                       
Line         Property   string Line {get;set;}                                           
LineNumber   Property   int LineNumber {get;set;}                                        
Matches      Property   System.Text.RegularExpressions.Match[] Matches {get;set;}        
Path         Property   string Path {get;set;}                                           
Pattern      Property   string Pattern {get;set;}                                        

And other properties, such as Pattern and Line work:

PS H:\> $c.Pattern
ab

PS H:\> $c.Line
abd 14e 568

Also, no error is generated when sending an index value to the Matches array:

PS H:\> $c.Matches[0]

PS H:\> 

I am not certain how to interpret the results, nor am I certain why it is occuring.

This behavior is problematic, as there are many times I must search for strings that contain regex special characters, ()'s are very common.

Expanding on the example:

PS H:\> $c = "ab(d) 14e 568" | Select-String -Pattern "ab(d)"

PS H:\> $c.Matches

PS H:\> 

$c.Matches returns nothing, and $c itself is null, due to the use of the parentheses in the regex pattern:

PS H:\> $c -eq $null
True

Using -SimpleMatch does produce a MatchInfo object, but still does not return any matches:

PS H:\> $c = "ab(d) 14e 568" | Select-String -Pattern "ab(d)" -SimpleMatch

PS H:\> $c -eq $null
False

PS H:\> $c.Matches

PS H:\> 

The work-around I found (here on SO) is to use the Regex.Escape method from .NET:
(reference: Powershell select-string fails due to escape sequence)

PS H:\> $pattern = "ab(d)"
$pattern = ([regex]::Escape($pattern))
$c = "ab(d) 14e 568" | Select-String -Pattern $pattern

PS H:\> $c.Matches


Groups   : {ab(d)}
Success  : True
Captures : {ab(d)}
Index    : 0
Length   : 5
Value    : ab(d)

As this workaround returns the expected matches from Select-String, I have been able to continue my scripting.

But I am curious as to why no matches are returned when using the -SimpleMatch parameter.

...
With regards,
Schwert

回答1:

From Get-Help Select-String -Parameter SimpleMatch:

-SimpleMatch [<SwitchParameter>]

Uses a simple match rather than a regular expression match. In a simple match, Select-String searches the input for the text in the Pattern parameter. It does not interpret the value of the Pattern parameter as a regular expression statement.

So, SimpleMatch simply does a substring search for $Pattern inside each string you pipe to it. It returns a MatchInfo object containing the string and relevant contextual information if present, but no Matches since a proper regex matching was never carried out against the string - it's as simple as that