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 не является одним из доступных вариантов.