Powershell Regex возвращает только первый результат

Почему мой шаблон регулярного выражения возвращает только имя / значение первого теста? Я подумал. + Сделает это не жадным шаблоном.

Это мой код

$value = "Starting test: Connectivity
          Starting test: CheckSecurityError
          Starting test: DFSREvent"


$value -match 'Starting test: (?<testName>.+)' 

$matches.testName

Это мой результат

True
Connectivity

person KingBain    schedule 29.06.2017    source источник
comment
Если это похоже на другие механизмы регулярных выражений, точка не соответствует символам новой строки, если вы этого не укажете. Так же, как и у вас, группа захвата будет включать в себя секунды две Start test: строки, а также все пробелы.   -  person Dewi Morgan    schedule 29.06.2017
comment
Что именно вы хотите вернуть?   -  person Matt    schedule 29.06.2017


Ответы (3)


$value = @"
Starting test: Connectivity
Starting test: CheckSecurityError
Starting test: DFSREvent
"@

$Pattern = '^\s*Starting test: (?<testName>.+?)$'
($value -split '\n')|
    Where-Object {$_ -match $Pattern }|
      ForEach{$matches.testname}

"-----------------"
## alternative without named capture group

$value -split '\n' | 
  select-string -pattern  'Starting test: (.+)' -all | 
    ForEach {$_.matches.groups[1].value}

Пример вывода:

Connectivity
CheckSecurityError
DFSREvent
-----------------
Connectivity
CheckSecurityError
DFSREvent
person Community    schedule 29.06.2017

Один из подходов - использовать класс .Net, System.Text.RegularExpressions.Regex:

$value = "Starting test: Connectivity
          Starting test: CheckSecurityError
          Starting test: DFSREvent"
$regex = [System.Text.RegularExpressions.Regex]::new('Starting test: (?<testName>.+)')
$regex.Matches($value) | %{$_.Groups['testName'].value}

#or by calling the static method rather than instantiating a regex object:
#[System.Text.RegularExpressions.Regex]::Matches($value, 'Starting test: (?<testName>.+)') | %{$_.Groups['testName'].value}

Вывод

Connectivity
CheckSecurityError
DFSREvent

Или вы можете использовать Select-String, как упоминалось в других ответах /, только используя %{$_.Groups['testName'].value, чтобы извлечь значения соответствующих групп захвата из ваших совпадений.

$value | 
    select-string -Pattern 'Starting test: (?<testName>.+)' -AllMatches | 
    % Matches | 
    %{$_.Groups['testName'].value} 
person JohnLBevan    schedule 29.06.2017

Вы должны использовать select-string:

$value -split '\n' | sls 'Starting test: (?<testName>.+)' | % { Write-Host 'Result' $_ }
person majkinetor    schedule 29.06.2017
comment
Как мне сделать это как многострочное регулярное выражение? - person KingBain; 29.06.2017
comment
Добавьте параметр -AllMatches в вызов select-string. Не строго multi-line в определении регулярного выражения (т. Е. Изменение поведения ^ и $, но это означает, что он может возвращать более одного совпадения, что, я думаю, именно то, что вам нужно. Т.е. действует так, как если бы был применен модификатор Global (w3schools.com/jsref/jsref_regexp_g.asp) - person JohnLBevan; 29.06.2017