是否可以使用 `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
其中 Index
和 Length
指定每个匹配项的位置。
但是,我找不到如何在使用 switch -regex
时获取每个匹配项的位置。例如:
switch -regex ('abcxyzabc') {
'abc(?<x>.*)abc' {
$matches
}
}
给出:
Name Value
---- -----
x xyz
0 abcxyzabc
我找不到 Index
和 Length
之类的东西来获取 $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 获取更多信息。
获取匹配-位置信息(起始索引,长度)需要以下之一:
Select-String
cmdlet,如您的问题所示。
直接使用底层[regex]
class(System.Text.RegularExpressions.Regex
).
将后者应用于您的示例:
PS> [regex]::Match('abcxyzabc', 'abc(?<x>.*)abc')
Groups : {0, x}
Success : True
Name : 0
Captures : {0}
Index : 0
Length : 9
Value : abcxyzabc
向您展示了一种通过 switch
.
提供此功能的有点麻烦的方法
一种更有效的方法是将 foreach
statement 与 if
语句结合起来:
foreach ($str in 'abcxyzabc', '...') {
if (($match = [regex]::Match($str, 'abc(?<x>.*)abc')).Success) { <# ... #> }
elseif (($match = [regex]::Match($str, 'cde(?<x>.*)cde')).Success) { <# ... #> }
# ...
}
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
其中 Index
和 Length
指定每个匹配项的位置。
但是,我找不到如何在使用 switch -regex
时获取每个匹配项的位置。例如:
switch -regex ('abcxyzabc') {
'abc(?<x>.*)abc' {
$matches
}
}
给出:
Name Value
---- -----
x xyz
0 abcxyzabc
我找不到 Index
和 Length
之类的东西来获取 $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
获取匹配-位置信息(起始索引,长度)需要以下之一:
Select-String
cmdlet,如您的问题所示。直接使用底层
[regex]
class(System.Text.RegularExpressions.Regex
).
将后者应用于您的示例:
PS> [regex]::Match('abcxyzabc', 'abc(?<x>.*)abc')
Groups : {0, x}
Success : True
Name : 0
Captures : {0}
Index : 0
Length : 9
Value : abcxyzabc
switch
.
一种更有效的方法是将 foreach
statement 与 if
语句结合起来:
foreach ($str in 'abcxyzabc', '...') {
if (($match = [regex]::Match($str, 'abc(?<x>.*)abc')).Success) { <# ... #> }
elseif (($match = [regex]::Match($str, 'cde(?<x>.*)cde')).Success) { <# ... #> }
# ...
}