如何使用正则表达式捕获多个未知数量的值

时间:2018-04-27 21:50:36

标签: regex powershell

我想使用正则表达式捕获多个字符串。我希望$匹配包含digitadigitbdigitc值。它似乎捕获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 :(得分:2)

您可以撤消问题并执行以下操作:

,"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 

答案 1 :(得分:1)

PowerShell的 -match运算符只能找到(最多)一个匹配,之后会反映在自动$Matches变量中。 [ 1]

正如Wiktor Stribiżew在对该问题的评论中暗示的那样,使用基础 .NET [regex]类及其静态.Matches() method直接返回所有匹配

但是,编写正则表达式的方式,每个匹配将包含所有3个捕获组(digitadigitb,{{1只有其中一个包含捕获的值,这使得访问结果变得很尴尬。

以下(PSv4 +语法)改为使用:

  • 数字(digitc
  • 的通用命名捕获组
  • letter 的一般命名捕获组(?(<digit>...)
  • 无替代(?(<letter>...)

这样每个匹配包含2个捕获组,分别包含捕获的字母和数字。

|

在PSv3中,您可以使用$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 }) 语句来迭代匹配项(foreach)。

以上产量:

foreach ($match in $allMatches) { ... }

请注意,letter: a - digit: 3 letter: c - digit: 5 letter: b - digit: 4 返回的是[System.Text.RegularExpressions.MatchCollection]个实例,它是[System.Text.RegularExpressions.Match]个实例的集合。

替代是将 Select-String[regex]::Matches()开关一起使用,但更慢 - 其中根据用例(PSv2 +)可能或不重要:

-AllMatches

$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 } 输出[Microsoft.PowerShell.Commands.MatchInfo]个实例,其Select-Object属性包含一组[System.Text.RegularExpressions.Match]个实例。

[1] .Matches包含$Matches个实例,其[hashtable]条目包含整体匹配,而捕获组从条目0开始,如果未命名;命名捕获组可以通过其名称访问,例如问题示例中的1