【问题标题】:Why JS Regexp.exec returns an array with more elements than expected?为什么 JS Regexp.exec 返回一个包含比预期更多元素的数组?
【发布时间】:2020-12-18 06:44:39
【问题描述】:

我正在尝试正则表达式匹配各种持续时间字符串(例如 1d10h、30m、90s 等),并提出了一个正则表达式字符串将字符串拆分为多个片段,但似乎我得到了两个未定义的结果在不应该存在的末端。我想这与通过 ? 分组的贪婪匹配有关,但我不知道如何解决它。

我的代码如下所示:

const regex = /^(\d+?[d])?(\d+?[h])?(\d+[m])?(\d+[s])?$/gmi
const results = regex.exec('1d10h')

我得到的结果是这样的:

[
  "1d10h",
  "1d",
  "10h",
  undefined,
  undefined,
]

我只期待前三个结果(实际上,我只想要1d10h),但剩下的两个undefined 结果不断弹出。

【问题讨论】:

  • 您有 4 个捕获组,由于它们是可选的,因此您必须在之后手动过滤掉 undefineds

标签: javascript regex matching regex-group


【解决方案1】:

您在正则表达式中有 4 个组 - 每个组都用大括号 ( ... ) 括起来并自然地枚举 - 较早的左大括号出现在表达式中,组的序号越低。

当然,整场比赛可以被命名为“零”组。

所以,regex.exec('1d10h') 的结果包含 5 个项目:

  • results[0] - 整个表达式匹配
  • results[i] - 每组比赛,i in {1,2,3,4}

因为在这种情况下,每个组都是可选的(后跟 ?) - 允许使用 undefined 代替任何不匹配的组。

很容易看出,如果您在不匹配的组后删除? 符号,整个表达式将无法匹配,因此regex.exec('1d10h') 将返回null

要去除未定义的元素,只需将它们过滤掉:

const result = regex.exec('1d10h').filter(x => x);

【讨论】:

  • 可以使用静态函数Boolean.filter(Boolean)进行过滤
  • 啊,我明白你的意思了——当我多看一点的时候,它是有道理的,我会继续把它标记为正确的,谢谢!
  • 你可以切掉第一个元素:regex.exec('1d10h')?.filter(Boolean).slice(1) - 如果正则表达式不匹配,optional chaining operator?. 使它返回undefined,但它是not available in all browsers
猜你喜欢
  • 2012-10-01
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多