【问题标题】:Named capture group within optional non-capturing group可选非捕获组中的命名捕获组
【发布时间】:2020-05-13 15:26:28
【问题描述】:

我有以下 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 ':'),所以这个问题只是为了学术兴趣。

【问题讨论】:

  • 你确定你会期望AppId AND LicNr2 输入ADM:Dev_ControllerStore_103:1:2

标签: regex powershell powershell-5.0


【解决方案1】:

\S 模式匹配任何非空白字符,包括 : 和数字。您可以使用惰性\S+? 模式'^(?&lt;UID&gt;\S+?):(?&lt;DB&gt;\S+?):(?&lt;AppId&gt;\d+)(?::(?&lt;LicNr&gt;\d+))?$' 来修复该模式,但也可以使用更精确的模式,该模式将使用更适合您的输入的模式:

^(?<UID>\w+):(?<DB>\w+):(?<AppId>\d+)(?::(?<LicNr>\d+))?$

regex demo

详情

  • ^ - 字符串开头
  • (?&lt;UID&gt;\w+) - 组 UID:一个或多个单词字符
  • : - 冒号
  • (?&lt;DB&gt;\w+) - 组 DB:一个或多个单词字符
  • : - 冒号
  • (?&lt;AppId&gt;\d+) - 组 AppId:一位或多位数字
  • (?::(?&lt;LicNr&gt;\d+))? - 可选组::,然后是 Group LicNr:1+ 位
  • $ - 字符串结束。

【讨论】:

  • 啊当然;我没有注意字符串的开头/甚至没有考虑修改\S;谢谢你;我现在修改了我的代码以使用 [^\:] 来匹配那里的任何非冒号。
  • @JohnLBevan 好的,另外,如果你知道不能有空格,你可以使用[^\s:]。请不要逃避;,因为它在任何正则表达式中都没有什么特别之处。
【解决方案2】:

由于您想在 : 上拆分并在末尾有一个可选部分,因此请在该选项之前使您的量词不贪婪:

$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 

【讨论】:

    猜你喜欢
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 2012-09-22
    • 1970-01-01
    • 2014-08-01
    • 2023-04-03
    • 2014-09-11
    相关资源
    最近更新 更多