如何在Powershell中获得正则表达式的所有匹配(所有位置都被考虑)?

时间:2018-04-19 16:35:52

标签: .net regex powershell

鉴于下面的代码,在0,2和4位也有匹配,因为b*匹配空字符串。

PS C:\Users\admin> [regex]$regex = "ab*"

PS C:\Users\admin> $regex.Matches("ababab")

Groups   : {0}
Success  : True
Name     : 0
Captures : {0}
Index    : 0
Length   : 2
Value    : ab

Groups   : {0}
Success  : True
Name     : 0
Captures : {0}
Index    : 2
Length   : 2
Value    : ab

Groups   : {0}
Success  : True
Name     : 0
Captures : {0}
Index    : 4
Length   : 2
Value    : ab

我希望结果集能够包含匹配的a的上述位置。

另外,请考虑以下示例:

PS C:\Users\admin> [regex]::Matches("aaaa", "aa?")


Groups   : {0}
Success  : True
Name     : 0
Captures : {0}
Index    : 0
Length   : 2
Value    : aa

Groups   : {0}
Success  : True
Name     : 0
Captures : {0}
Index    : 2
Length   : 2
Value    : aa

在这种情况下,每个位置都有匹配,但只报告两个结果。

如何让Powershell在每个位置都匹配正则表达式,以便所有匹配都包含在结果集中?

1 个答案:

答案 0 :(得分:1)

ab*中,*表示b贪婪零或更多。它会尽可能匹配,这就是你得到ab的原因。如果您只想要a,请使用ab*?使其变得懒惰。然后它将避免b - 字符。如果您想要两个位置,请使用组来拆分匹配的值。您会发现每个组都有Index

[regex]$regex = "(a)(b*)"
$regex.Matches("ababab").Groups | ft Value, Index, Length -AutoSize  

Value Index Length
----- ----- ------
ab        0      2
a         0      1
b         1      1
ab        2      2
a         2      1
b         3      1
ab        4      2
a         4      1
b         5      1

您也可以尝试使用不会消耗普通模式和嵌套组等字符的外观来捕获值。例如:

[regex]::Matches("aaaa", "(?=(aa?))").Groups | ? { $_.Value } | ft Value, Index, Length -AutoSize

Value Index Length
----- ----- ------
aa        0      2
aa        1      2
aa        2      2
a         3      1

#Making it lazy will return only the single a's
[regex]::Matches("aaaa", "(?=(aa??))").Groups | ? { $_.Value } | ft Value, Index, Length -AutoSize

Value Index Length
----- ----- ------
a         0      1
a         1      1
a         2      1
a         3      1

#Using nested groups can capture both
[regex]::Matches("aaaa", "(?=((a)a?))").Groups | ? { $_.Value } | ft Value, Index, Length -AutoSize

Value Index Length
----- ----- ------
aa        0      2
a         0      1
aa        1      2
a         1      1
aa        2      2
a         2      1
a         3      1
a         3      1

#Removing duplicates (might be fixable in the regex too, but I'm tired)
[regex]::Matches("aaaa", "(?=((a)a?))").Groups | ? { $_.Value } | Select-Object -Property Value, Index, Length -Unique | Ft -AutoSize
Value Index Length
----- ----- ------
aa        0      2
a         0      1
aa        1      2
a         1      1
aa        2      2
a         2      1
a         3      1