【问题标题】:Capture optional capture group next to first group在第一组旁边捕获可选的捕获组
【发布时间】:2018-07-19 14:09:17
【问题描述】:

给定两个字符串

hello/world/thomas

还有:

hello/world

我有以下正则表达式

hello/(.+)(/(.+))?

第二组是可选的。

我希望有以下小组赛:

['world', 'thomas']

但我得到了:

['world/thomas']

第二个字符串按预期工作:

['world']

我怎样才能产生预期的结果。

https://regexr.com/3kh06

【问题讨论】:

  • 使用否定字符类:hello/([^/]+)(/([^/]+))?
  • @WiktorStribiżew 只是出于好奇(据我所知)[] 被认为是一个类、一个集合还是两者兼而有之?这些术语似乎可以互换使用。
  • @ctwheels 在 POSIX 上下文中,它被称为 括号表达式(以免与诸如 [:digit:] 之类的 POSIX 字符类混淆)。在 NFA 世界中,它通常称为字符类,有时也称为字符集(可互换使用)。
  • 只在第一组中使用惰性量词
  • 如果是hello/world/today/is/thomas/tommorrow/is/james,你想匹配什么?无论如何,如果是定位的,你不能使用像.+? 这样的东西而不用它后面的字符来锚定它。如果后面的 all 是可选的,则它选择不匹配任何内容。最好坚持使用带有可选量词的否定类​​[^/]*

标签: regex capture-group


【解决方案1】:

您的模式 - hello/(.+)(/(.+))? - 匹配 hello/,然后 (.+) 抓取该行的所有其余部分,将其放入第 1 组,然后检查它是否可以匹配其余文本(此时,空文本在字符串的末尾)使用(/(.+))? 模式 - 由于? 量词(= 零次或多次重复),它可以匹配空字符串。

您可以将 . 替换为 [^/] negated character class 以避免匹配除换行符以外的所有字符:

var rx = new RegExp("hello/([^/]+)(?:/([^/]+))?", "g")

regex demo

说明

  • hello/ - 文字子字符串
  • ([^/]+) - 第 1 组:/ 以外的任何一个或多个字符
  • (?:/([^/]+))? - 一个可选的非捕获组,匹配 1 次或 0 次
    • / - 一个 / 字符
    • ([^/]+) - 第 2 组:/ 以外的一个或多个字符。

JS 演示:

var strs = ['hello/world/thomas', 'hello/world'];      // Demo strings
var rx = new RegExp("hello/([^/]+)(?:/([^/]+))?", "g") // Regex (constructor used due to many / inside
for (var s of strs) {                                  // Demo loop
  var res = [], m;
  while(m = rx.exec(s)) {                              // Check for multiple matches
    res.push(m[1]);                                    // Adding Group 1 to results
    if (m[2]) res.push(m[2]);                         // Adding Group 2 to results if exists
  }
  console.log(s, res);                                // Demo result display
  
}

【讨论】:

    猜你喜欢
    • 2012-09-22
    • 2011-05-16
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 2013-03-06
    相关资源
    最近更新 更多