【问题标题】:Regex Capturing Group with alternative doesn't match正则表达式捕获组与替代不匹配
【发布时间】:2021-05-28 19:47:39
【问题描述】:

我有以下字符串,我想在其中匹配有效的<key>:<value> 对。

有效的<key> 是任何带有非空白字符后跟:
一个有效的<value> 要么包含在[] 中,要么包含在一个没有空格的字符串中。

key1:value1 key#2:@value#2 nyet key3:[@value#3, value4] key4:[value5] :bar

基本上我想匹配除nyet:bar 之外的所有内容

我想出了以下正则表达式\S+:(\S+|\[[^]]+\]),但它似乎与key3:[@value#3, value4] 中的表达式不匹配。在捕获组中,第二种选择\[[^]]+\]应该匹配这个表达式,所以我不明白为什么它不匹配。

以下正则表达式有效:\S+:([^([ )]+|\[[^\]]+\]),但感觉不优雅。

问题:

  1. 为什么第一个正则表达式 \S+:(\S+|\[[^]]+\]) 不起作用?
  2. 如何找到更优雅的解决方案来匹配键值对?

【问题讨论】:

  • ([^\s:]+):(?|\[([^][]*)]|(\S+)) 可能适合您的场景,但它需要 PCRE/Boost。见demo
  • 您的第一个正则表达式不起作用,因为 \S+ 替代方案放在第一位。它总是“获胜”,因为 [ 也是非空格。

标签: regex capturing-group


【解决方案1】:

在模式中你可以switch the alternatives\S+:(\[[^]]+\]|\S+),但在这种情况下也可以匹配[]

您也可以 exclude 使用否定字符类匹配第一部分中的 : [^\s:]+:(\[[^]]+]|\S+)

对于组,您可以使用交替并检查值是否存在组 2 或组 3。

([^\s:]+):(?:\[([^][]+)]|(\S+))

模式匹配:

  • ([^\s:]+) 捕获 group 1,匹配除空白字符或 : 之外的任何字符
  • : 匹配 :
  • (?:非捕获组
    • \[([^][]+)] 匹配[group 2 中捕获除[] 之外的任何字符并匹配结束]
    • |
    • (\S+)组 3 中捕获 1+ 个非空白字符
  • )关闭非捕获组

Regex demo


如果支持 conditional,您可以检查第 2 组是否捕获了 [。如果是这样,您可以捕获除第 3 组中的括号之外的任何字符。

然后你想要的值在第 1 组和第 3 组中。

([^\s:]+):(?:(\[)(?=[^][]*]))?((?(2)[^][]+|\S+))\]?

Regex demo

【讨论】:

    【解决方案2】:
    1. 你的正则表达式很接近。它失败了,因为:\S 优先于:\[
    2. 此正则表达式有效:
    /\S+:(?:\[[^\]]*\]|\S+)/g
    

    解释:

    • \S+: - 1+ 个非空格字符和一个冒号
    • (?: - 非捕获组开始(用于 OR)
      • \[[^\]]*\] - [...] 模式
      • | - 逻辑或
      • \S+ - 1+ 非空格字符
    • ) - 非捕获组结束

    【讨论】:

    • @Frode Akselsen:这符合您的需求吗?有什么问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2014-01-30
    • 2021-11-14
    • 2021-04-08
    • 2015-08-05
    相关资源
    最近更新 更多