Как перехватить несколько неизвестных значений с помощью регулярных выражений - PullRequest
0 голосов
/ 28 апреля 2018

Я хотел бы захватить несколько строк с помощью регулярного выражения. Я надеялся, что $ match будет содержать значения digita, digitb и digitc. Похоже, чтобы захватить digita и остановить. Если возможно, я бы хотел, чтобы захват был независимым от порядка. Как я могу это сделать?

PS C:\src\t> $s2 = 'a=3 c=5 b=4'
PS C:\src\t> $s2 -match 'a=(?<digita>[0-9])|b=(?<digitb>[0-9])c=(?<digitc>[0-9])'
True
PS C:\src\t> $matches

Name                           Value
----                           -----
digita                         3
0                              a=3

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Оператор PowerShell -match только когда-либо находит (самое большее) одно совпадение, впоследствии отраженное в автоматической $Matches переменной . [1]

Как Wiktor Stribiżew намекает на комментарий в вопросе, используя базовый класс .NET [regex] с его статическим .Matches() методом , непосредственно возвращающим все совпадений .

Однако, как написано ваше регулярное выражение, каждое совпадение будет содержать все 3 группы захвата (digita, digitb, digitc), только с одной из они содержат захваченное значение, что затрудняет доступ к результатам.

Вместо этого используется следующий синтаксис (PSv4 +):

  • универсально названная группа захвата для цифры (?(<digit>...))
  • группа имен с общим названием для буквы (?(<letter>...))
  • без чередования (|)

, чтобы каждое совпадение содержало 2 группы захвата, содержащие соответственно захваченную букву и цифру.

$s2 = 'a=3 c=5 b=4'
$allMatches = [regex]::Matches($s2, '(?<letter>[abc])=(?<digit>[0-9])')
$allMatches.ForEach({ 
  'letter: {0} - digit: {1}' -f  $_.Groups['letter'].value, $_.Groups['digit'].value 
})

В PSv3- вы можете использовать оператор foreach для перебора совпадений (foreach ($match in $allMatches) { ... }).

Вышеуказанные выходы:

letter: a - digit: 3
letter: c - digit: 5
letter: b - digit: 4

Обратите внимание, что [regex]::Matches() возвращает экземпляр [System.Text.RegularExpressions.MatchCollection], который является коллекцией [System.Text.RegularExpressions.Match] экземпляров.


Альтернативой является использование Select-String с переключателем -AllMatches , который, однако, на медленнее - что может или может не иметь значения, в зависимости от варианта использования (PSv2 +):

$s2 = 'a=3 c=5 b=4'
$s2 | Select-String -AllMatches '(?<letter>[abc])=(?<digit>[0-9])' |
  Select-Object -ExpandProperty Matches | ForEach-Object { 
    'letter: {0} - digit: {1}' -f  $_.Groups['letter'].value, $_.Groups['digit'].value
  }

Select-Object выводит [Microsoft.PowerShell.Commands.MatchInfo] экземпляров, чье свойство .Matches содержит массив, опять же, [System.Text.RegularExpressions.Match] экземпляров.


[1] $Matches содержит экземпляр [hashtable], чья запись 0 содержит общее совпадение, а группы захвата начинаются с записи 1, если она не указана; Именованные группы захвата могут быть доступны по их имени, например $Matches.digita в примере из вопроса.

0 голосов
/ 28 апреля 2018

Вы можете решить проблему и сделать что-то вроде этого:

,"a","b","c" | % { "$_=(?<digit$_>[0-9])" } | % { $s2 -match $_ } | % { $matches }

Выходы

Name                           Value                                                                                                                                                                   
----                           -----                                                                                                                                                                   
digita                         3                                                                                                                                                                       
0                              a=3                                                                                                                                                                     
digitb                         4                                                                                                                                                                       
0                              b=4                                                                                                                                                                     
digitc                         5                                                                                                                                                                       
0                              c=5 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...