是否可以使用 `switch -regex` 获得匹配位置

Is it possible to get match position using `switch -regex`

Select-String -Pattern returns 每个匹配项的位置。例如:

$s = 'abcxyzabc' | Select-String -Pattern 'abc(?<x>.*)abc'
$s.Matches[0].Groups | Select-Object Name, Value, Index, Length

给出:

Name Value     Index Length
---- -----     ----- ------
0    abcxyzabc     0      9
x    xyz           3      3

其中 IndexLength 指定每个匹配项的位置。

但是,我找不到如何在使用 switch -regex 时获取每个匹配项的位置。例如:

switch -regex ('abcxyzabc') {
    'abc(?<x>.*)abc' {
        $matches
    }
}

给出:

Name                           Value
----                           -----
x                              xyz
0                              abcxyzabc

我找不到 IndexLength 之类的东西来获取 $matches 中的匹配位置。

我还检查了Select-String -Pattern返回的Matches的类型是System.Text.RegularExpressions.Match[],而switch -regex$matches的类型是[=26] =].

我是不是漏掉了什么,或者 switch -regex 不应该给出每场比赛的地点?

继续我的评论。

https://adamtheautomator.com/powershell-switch/#Using_the_-RegEx_Parameter

Referencing the code below, the first line will import the contents of the RegExp.txt and store it in the $RegExp variable. Then, the Powershell switch statement uses the email.txt file as the input for test values as indicated by the -file parameter.

$RegExp = Get-Content .\RegExp.txt
switch -regex -file .\email.txt {
    $RegExp {"[$_] is an email address"}
    Default {"[$_] is NOT an email address"}
}

Once the code above is run in PowerShell, only the test value that matches the regular expression stored in the $RegExp will be validated.

https://riptutorial.com/powershell/example/3791/switch-statement-with-regex-parameter

The -Regex parameter allows switch statements to perform regular expression matching against conditions.

switch -Regex ('Condition')
{ 
  'Con\D+ion'    {'One or more non-digits'}
  'Conditio*$'   {'Zero or more "o"'} 
  'C.ndition'    {'Any single char.'}  
  '^C\w+ition$'  {'Anchors and one or more word chars.'} 
  'Test'         {'No match'} 
}

更新

相对于@daniel 替代的有用方法,结合您的努力;可以重构为这个。

switch -regex ('abcxyzabc') 
{
    {($script:myMatches = [regex]::Matches($PSItem, 'abc(?<x>.*)abc'))} 
    {
        $myMatches.Groups | 
        Select-Object Name, Value, Index, Length
    }
} 

# Results
<#
Name Value     Index Length
---- -----     ----- ------
0    abcxyzabc     0      9
x    xyz           3      3
#>

您可以使用这个丑陋的替代方案,它直接使用 Regex class 并会给您索引和长度

$values = @(
    'abcxyzabc'
    'cat in the hat'
    'the dogg pound'
)

switch ($values) {
    {($script:myMatches = [regex]::Matches($_, 'abc(?<x>.*)abc'))} {
        $myMatches.Groups[1]
    }
    {($script:myMatches = [regex]::Matches($_, 'cat(?<x>.*)hat'))} {
        $myMatches.Groups[1]
    }
}

结果

Success  : True
Name     : x
Captures : {x}
Index    : 3
Length   : 3
Value    : xyz

Success  : True
Name     : x
Captures : {x}
Index    : 3
Length   : 8
Value    :  in the

Did I miss anything or is switch -regex not supposed to give the location of each match?

确实,switch 语句的 -Regex 开关和(有效的)底层
-match operator are designed to provide information other than what text was captured
, via the automatic $Matches variable - see 获取更多信息。

获取匹配-位置信息(起始索引,长度)需要以下之一:

将后者应用于您的示例:

PS> [regex]::Match('abcxyzabc', 'abc(?<x>.*)abc')

Groups   : {0, x}
Success  : True
Name     : 0
Captures : {0}
Index    : 0
Length   : 9
Value    : abcxyzabc

向您展示了一种通过 switch.

提供此功能的有点麻烦的方法

一种更有效的方法是将 foreach statementif 语句结合起来:

foreach ($str in 'abcxyzabc', '...') {
  if     (($match = [regex]::Match($str, 'abc(?<x>.*)abc')).Success) { <# ... #> }
  elseif (($match = [regex]::Match($str, 'cde(?<x>.*)cde')).Success) { <# ... #> }
  # ...
}