PowerShell -match-оператор и несколько групп

У меня есть следующая запись в журнале, которую я обрабатываю в PowerShell. Я пытаюсь извлечь все имена активности и длительности с помощью оператора -match, но я получаю только одну группу ответов. Я не получаю все совпадения, которые вижу, когда я делаю то же самое в С#, используя объект Regex. Может кто-нибудь объяснить, что я делаю неправильно?

Соответствующий 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

Выход

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)

Ответ 1

Вы можете сделать это с помощью командлета Select-String в V2, но вам нужно указать ключ -AllMatches, например:

$formattedMessage | Select-String 'regexpattern' -AllMatches

Имейте в виду, что с оператором -match главное, что вы делаете, - это поиск "a", то есть соответствие шаблону регулярного выражения или нет.

Ответ 2

Мне удалось получить все группы, указав Regex, а затем вызывая .Matches в этом регулярном выражении. Все еще интересно узнать, можно ли это сделать с помощью оператора -match в 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)

Ответ 3

Оператор -match предназначен для использования только один раз; он не выполняет глобальное совпадение на входе. Keith Hill предложил предложение для оператора -matchall на Microsoft connect здесь.

Я предлагаю другой способ сделать это. Если запись журнала находится в файле, вы можете использовать оператор 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

Ответ 4

http://www.johndcook.com/regex.html дает достойный пример

И, конечно, упростите свое выражение:

^([^-]+)\s*-\s*duration\(([0-9]+)
  • начало в начале строки
  • захватить все символы, ведущие к первому -
  • убедитесь, что есть -
  • пропустить пробелы
  • убедитесь, что слово "продолжительность (" существует
  • захватить все цифры после "duration ("

Ответ 5

Вы можете включить Regular Expression Options в выражении, но, к сожалению, Global не является одним из доступных вариантов.