PowerShell中的-match运算符和多个组

13

我正在使用PowerShell处理以下日志条目,尝试使用-match运算符提取所有活动名称和持续时间,但我只得到了一个匹配组。当我在C#中使用Regex对象进行相同的操作时,我没有获得所有的匹配项。有人能解释一下我做错了什么吗?

相关PowerShell脚本

$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

输出

Name  Value
----  -----
0     Get Client Model - duration(0
1     Get Client Model
2     0

日志条目示例:

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)
5个回答

11

你可以使用V2中的Select-String命令,但是你需要指定-AllMatches开关,例如:

$formattedMessage | Select-String 'regexpattern' -AllMatches

记住,使用-match运算符时,首要的事情是寻找“一个”匹配项,也就是说,正则表达式模式是否被匹配。


10
我定义了一个正则表达式,然后在该正则表达式上调用.Matches,就能获取所有的组。我仍然很好奇是否可以使用PowerShell中的-match运算符来完成这个任务。
$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)

最佳答案是,它允许您非常轻松地将结果分配给变量,因此您可以将其处理为匹配项数组。 - sonjz

4

http://www.johndcook.com/regex.html 提供了一个不错的例子。

而且,请务必简化你的表达式:

^([^-]+)\s*-\s*duration\(([0-9]+)
  • 从行首开始
  • 捕获第一个 - 之前的所有字符
  • 确保有一个 -
  • 跳过空格
  • 确保单词 "duration(" 存在
  • 捕获 "duration(" 后面的所有数字

我尝试按照你描述的方式简化正则表达式(在创建那个恶心的正则表达式之前),但PowerShell没有生成任何匹配项。 - Eric Schoonover
我使用了您的样本数据,并且使用上述确切表达式得到了正确的结果。 - genio
PowerShell将使用提供的正则表达式生成匹配项。 - James Pogran

4

-match操作符仅应使用一次;它不会对输入进行全局匹配。Keith Hill在Microsoft Connect 此处上提出了一个-matchall操作符的建议。

我将提出另一种方法来完成相同的操作,如果日志条目在文件中,则可以使用switch语句:

switch -regex -file .\log.txt { $entryRegex { $matches[1] + ", " + $matches[2] } }

如果$entryRegex包含您定义的正则表达式,则此语句将输出以下内容:
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

0

您可以在表达式中包含正则表达式选项,但遗憾的是,全局(Global)似乎不是可用选项之一。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接