我想使用正则表达式捕获多个字符串。我希望$匹配包含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
答案 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个捕获组(digita
,digitb
,{{1只有其中一个包含捕获的值,这使得访问结果变得很尴尬。
以下(PSv4 +语法)改为使用:
digitc
)?(<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
。