PowerShell -match operator and multiple groups
I have the following log entry that I am processing in PowerShell I'm trying to extract all the activity names and durations using the -match
operator but I am only getting one match group back. I'm not getting all of the matches that I see when I do the same thing in C# using the Regex
object. Can someone explain what I am doing wrong?
Relevant PowerShell Script
$formattedMessage -match "(Get\sClient\sModel|Parse\sExpression|Get\sAbstract\sQuery|Compile\sQuery|Execute\sQuery|Get\sQuery\sPlan\sComplexity|Async\sTotal|Total)\s-\sduration\(([0-9]*)" | out-null
$matches
Output
Name Value
---- -----
0 Get Client Model - duration(0
1 Get Client Model
2 0
Log Entry Example:
Timestamp: 11/9/2009 6:48:41 PM
Message:
Category: QueryService
Priority: 3
EventId: 1001
Severity: Information
Title: SPARQL Query Response
Machine: SPOON16-SERVER
App Domain: KnowledgeBaseHost.exe
ProcessId: 2040
Process Name: 开发者_如何学编程D:\QueryService\QSHost.exe
Thread Name:
Win32 ThreadId:8092
Extended Properties:
Key - Workflow_cbbdd58b-e574-4054-88d4-1dd7a56dc9d9
Timeout - 1800
Result Format - WireTable
Result from Registry - False
Compiled Query from Cache - True
Result Count - 28332
Query Plan Complexity - 661622
Get Client Model - duration(0) start(0)
Parse Expression - duration(0) start(0)
Get Abstract Query - duration(0) start(0)
Compile Query - duration(0) start(0)
Get Query Plan - duration(0) start(1)
Execute Query - duration(63695) start(1)
Get Query Plan Complexity - duration(0) start(63696)
Get Executed Operations - duration(0) start(63696)
Total - duration(63696) start(0)
Async Total - duration(63696) start(0)
You can do this with the Select-String cmdlet in V2, but you need to specify the -AllMatches switch, e.g.:
$formattedMessage | Select-String 'regexpattern' -AllMatches
Keep in mind that with the -match
operator the primary thing you are doing is looking for "a" match, i.e., is the regex pattern matched or not?
I was able to get all of the groups by defining a Regex and then calling .Matches on that Regex. I am still curious to know if this can be done with the -match operator in PowerShell.
$detailRegex = [regex]"(Get\sClient\sModel|Parse\sExpression|Get\sAbstract\sQuery|Compile\sQuery|Execute\sQuery|Get\sQuery\sPlan\sComplexity|Async\sTotal|Total)\s-\sduration\(([0-9]*)"
$detailRegex.Matches($formattedMessage)
http://www.johndcook.com/regex.html gives a decent example
And, by all means, simplify your expression:
^([^-]+)\s*-\s*duration\(([0-9]+)
- start at the beginning of the line
- capture all characters leading up to the first -
- make sure there's a -
- skip whitespace
- make sure the word "duration(" exists
- capture all digits after "duration("
The -match operator is meant to be used just once; it doesn't do a global match on the input. Keith Hill put a suggestion for a -matchall operator on Microsoft Connect here.
I'll suggest another way to do it. If the log entry is in a file, you can use the switch statement to accomplish the same thing:
switch -regex -file .\log.txt { $entryRegex { $matches[1] + ", " + $matches[2] } }
This is the output I get with this statement if $entryRegex
has the regular expression you defined:
Get Client Model, 0
Parse Expression, 0
Get Abstract Query, 0
Compile Query, 0
Execute Query, 63695
Get Query Plan Complexity, 0
Total, 63696
Async Total, 63696
You can include Regular Expression Options in an expression, but sadly, Global does not appear to be one of the available options.
精彩评论