【问题标题】:Matching Double String, how do I only match with 1 result?匹配双字符串,我如何只匹配 1 个结果?
【发布时间】:2019-08-19 21:22:45
【问题描述】:

我能够匹配正则表达式所需的字符串,但它匹配了两次。

https://regex101.com/r/KmgGwS/7

if ( $_.PSPath -match ("(?<=\::)(.*?)(?=\\)+")) {
  $matches.Values
}

例如,输入字符串是这样的:

'Microsoft.PowerShell.Security\Certificate::CurrentUser\Root\A43489159A520F0D93D032CCAF37E7FE20A8B419'

它期望得到:

当前用户

使用当前代码,它会两次获得该字符串

当前用户 当前用户

【问题讨论】:

  • 不会 "(?&lt;=\::)(.*?)(?=\\)+" 成为正则表达式引擎的 (?&lt;=\::)(.*?)(?=\)+ 吗?这将产生引擎错误...
  • @sln:在 PowerShell 中,反引号 (`) 用作双引号字符串文字中的转义字符; \ 字符逐字使用 - 请参阅 about_Quoting_Rules

标签: regex powershell


【解决方案1】:

tl;dr

$Matches[0]

包含您的正则表达式匹配的内容总体$Matches[1] 包含第一个(也是唯一的)捕获组(带括号的子表达式,(...))匹配的内容 - 在您的情况下,两个值都发生在一样。

除非您需要显式枚举整体匹配以及捕获组匹配,否则不要使用$Matches.Value

要枚举捕获组值only,即枚举所有匹配除了整体匹配,使用:

# Enumerate all matches except the overall one (key 0)
$Matches.GetEnumerator().Where({ $_.Key -as [int] -ne 0 }).Value 

automatic $Matches variable 是一个 散列表 (System.Collections.Hashtable ):

  • 条目0 ($Matches[0]) 包含正则表达式匹配的内容完整

  • 所有其他条目(如果有)包含 捕获组(带括号的子表达式,(...))匹配的 子字符串,条目 1 代表第一个捕获组的匹配,2 2nd,依此类推。

    • 如果您使用 已命名 捕获组(例如 (?&lt;foo&gt;...),则条目使用该名称(例如 $Matches['foo']$Matches.foo)。

    • 如果您使用 非捕获 组 ((?:...)),它们会导致 $Matches 中的 no 条目。

    • (同样,look-around assertions - (?&lt;=...)(?&lt;!...)(?=...)(?!...) - 会导致条目。)

      李>

至于你尝试了什么

$Matches.Values 输出散列表中 all 条目的值的 collection,表示整体匹配(条目 0)以及任何捕获组匹配。

由于您的正则表达式包含一个捕获组,该组可以有效地捕获与正则表达式相同的内容作为一个整体(.*?)$Matches.Values 会输出一个值集合,该集合相当于数组
'CurrentUser', 'CurrentUser',当输出到控制台时,会产生问题中显示的结果。

请注意,如果您的正则表达式碰巧不包含任何捕获组,如sln's answer 中的建议,$Matches.Values 可能出现返回一个单个字符串,但在实际上它返回一个 ICollection 实例,它恰好只有 一个 元素。

现在,单元素集合和标量之间的区别在 PowerShell 中可能通常无关紧要,但需要注意这一点,因为在某些情况下它很重要。


[1] 注意事项
* 如果正则表达式完全不匹配,$Matches 不会更新,因此之前的值可能会保留。
* 如果-match 的LHS 是一个数组(集合),-match 充当过滤器$Matches 不会更新。 请注意,$Matches 也在 switch -Regex statement 的分支处理程序中设置。

【讨论】:

  • 我实际上确实枚举并捕获了数组中的组匹配。因此,我使用的是 match.values。
  • @123testing123:那么你得到的正是你所要求的:条目0中的整体正则表达式匹配的值和捕获组1的值,恰好是你的情况也一样。那么,为什么 - 预期 - 结果让您感到惊讶,为什么您接受建议您不要使用捕获组的答案?
  • @123testing123 您是否将结果分配回$Matches?那是行不通的。抓紧$matches[1]
  • 从@123testing123 之前的问题来看,我怀疑输入 ($_.PSPath) 不是单个字符串值,而是一个字符串数组(行)。跨度>
  • @iRon: 但是如果 -match 操作的 LHS 是一个 array(一个可枚举的),-match 充当过滤器,而 $Matches 不是完全没有人口;此外,在我知道的所有情况下,提供者提供的 .PSPath 属性都是一个字符串。
【解决方案2】:

您看到的是匹配值和
组 1 值。两者都包含相同的东西。

如果您只想查看单个值,请删除捕获组。

 (?<= :: )
 .*? 
 (?= \\ )

或者,像这样(?&lt;=::).*?(?=\\)

【讨论】:

    猜你喜欢
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-24
    • 1970-01-01
    相关资源
    最近更新 更多