可选非捕获组中的命名捕获组
Named capture group within optional non-capturing group
我有以下 PowerShell 代码:
$input = 'ADM:Dev_ControllerStore_103:1:2'
$pattern = '^(?<UID>\S+)\:(?<DB>\S+)\:(?<AppId>\d+)(?:\:(?<LicNr>\d+))?$'
if ( $input -match $pattern ) {
$Matches
}
这给出了以下输出:
Name Value
---- -----
DB 1
AppId 2
UID ADM:Dev_ControllerStore_103
0 ADM:Dev_ControllerStore_103:1:2
虽然我希望如此:
Name Value
---- -----
DB 1
AppId 2
UID ADM:Dev_ControllerStore_103
LicNr 2
0 ADM:Dev_ControllerStore_103:1:2
即LicNr
包含在输出中。
注意:我得到的输出是输入字符串的预期输出:'ADM:Dev_ControllerStore_103:1'
... 并且工作正常。
如果我更改正则表达式使最后一个非捕获组成为非可选组,或者我删除了非捕获组,那么对于较长的输入字符串都可以正常工作;但显然这些不适合只有 3 个值而不是 4 个值的版本。
我是不是遗漏了什么,或者这是 PowerShell 中的错误?
注意:我有一个解决方法(~$a,$b,$c,$d = $input -split ':'
),所以这个问题只是出于学术兴趣。
\S
模式匹配任何非空白字符,包括 :
和数字。您可以使用惰性 \S+?
模式 '^(?<UID>\S+?):(?<DB>\S+?):(?<AppId>\d+)(?::(?<LicNr>\d+))?$'
来修复模式,但也可以使用更精确的模式,该模式将使用更适合您的输入的模式:
^(?<UID>\w+):(?<DB>\w+):(?<AppId>\d+)(?::(?<LicNr>\d+))?$
详情
^
- 字符串开头
(?<UID>\w+)
- 组 UID:一个或多个字符
:
- 冒号
(?<DB>\w+)
- 组数据库:一个或多个单词字符
:
- 冒号
(?<AppId>\d+)
- 组AppId:一位或多位
(?::(?<LicNr>\d+))?
- 一个可选组:a :
然后是 Group LicNr: 1+ digits
$
- 字符串结尾。
因为你想在 :
上拆分并在最后有一个可选部分,所以让你的量词在该选项之前是非贪婪的:
$input = 'ADM:Dev_ControllerStore_103:1:2'
$pattern = '^(?<UID>\S+?)\:(?<DB>\S+?)\:(?<AppId>\d+?)(?:\:(?<LicNr>\d+))?$'
if ( $input -match $pattern ) {
$Matches
}
输出:
Name Value
---- -----
DB Dev_ControllerStore_103
AppId 1
UID ADM
LicNr 2
0 ADM:Dev_ControllerStore_103:1:2
我有以下 PowerShell 代码:
$input = 'ADM:Dev_ControllerStore_103:1:2'
$pattern = '^(?<UID>\S+)\:(?<DB>\S+)\:(?<AppId>\d+)(?:\:(?<LicNr>\d+))?$'
if ( $input -match $pattern ) {
$Matches
}
这给出了以下输出:
Name Value
---- -----
DB 1
AppId 2
UID ADM:Dev_ControllerStore_103
0 ADM:Dev_ControllerStore_103:1:2
虽然我希望如此:
Name Value
---- -----
DB 1
AppId 2
UID ADM:Dev_ControllerStore_103
LicNr 2
0 ADM:Dev_ControllerStore_103:1:2
即LicNr
包含在输出中。
注意:我得到的输出是输入字符串的预期输出:'ADM:Dev_ControllerStore_103:1'
... 并且工作正常。
如果我更改正则表达式使最后一个非捕获组成为非可选组,或者我删除了非捕获组,那么对于较长的输入字符串都可以正常工作;但显然这些不适合只有 3 个值而不是 4 个值的版本。
我是不是遗漏了什么,或者这是 PowerShell 中的错误?
注意:我有一个解决方法(~$a,$b,$c,$d = $input -split ':'
),所以这个问题只是出于学术兴趣。
\S
模式匹配任何非空白字符,包括 :
和数字。您可以使用惰性 \S+?
模式 '^(?<UID>\S+?):(?<DB>\S+?):(?<AppId>\d+)(?::(?<LicNr>\d+))?$'
来修复模式,但也可以使用更精确的模式,该模式将使用更适合您的输入的模式:
^(?<UID>\w+):(?<DB>\w+):(?<AppId>\d+)(?::(?<LicNr>\d+))?$
详情
^
- 字符串开头(?<UID>\w+)
- 组 UID:一个或多个字符:
- 冒号(?<DB>\w+)
- 组数据库:一个或多个单词字符:
- 冒号(?<AppId>\d+)
- 组AppId:一位或多位(?::(?<LicNr>\d+))?
- 一个可选组:a:
然后是 Group LicNr: 1+ digits$
- 字符串结尾。
因为你想在 :
上拆分并在最后有一个可选部分,所以让你的量词在该选项之前是非贪婪的:
$input = 'ADM:Dev_ControllerStore_103:1:2'
$pattern = '^(?<UID>\S+?)\:(?<DB>\S+?)\:(?<AppId>\d+?)(?:\:(?<LicNr>\d+))?$'
if ( $input -match $pattern ) {
$Matches
}
输出:
Name Value
---- -----
DB Dev_ControllerStore_103
AppId 1
UID ADM
LicNr 2
0 ADM:Dev_ControllerStore_103:1:2