regex 如何使中间捕获组在被通配符包围时工作?

cu6pst1q  于 2022-11-18  发布在  其他
关注(0)|答案(1)|浏览(118)

我经常使用正则表达式,虽然我不是高手,但我也惊讶于这是多么的困难。
我们有一个如下的正则表达式字符串:

^(?:remind me ).*? (to|that|about|its|it's)? ?(.*)$

我希望它与以下两个字符串匹配,* 和 * 为第一个捕获组分配某个值。

  • 在24小时测试中提醒我
  • 提醒我在24小时内****测试

将这个小“to”分配给第一个捕获组被证明是非常困难的。
我可以像下面这样做两遍,然后检查结果是否是null,来解决这个问题,但这似乎很疯狂,所以我希望能学到一种更好的方法。

const regex1 = /^(?:remind me ).*? (to|that|about|its|it's)? ?(.*)$/i
const regex2 = /(to|that|about|its|it's) ?(.*)$/i

const matches1 = 'remind me in 24 hours to test'.match(regex1)[2]
const matches2 = matches1.match(regex2)

console.log(matches2)
// String1 output: null
// String2 output: [ 'to test', 'to', 'test', index: 9, input: '24 hours to test', groups: undefined ]

关于相关问题:
我已经看到了许多关于这个问题的其他问题-但没有一个“解决方案”似乎适用于这里,因为大多数答案是定制的用户的具体问题,我还没有能够找出如何解决我们的问题使用他们作为参考。
我读了this answer,它提高了我对贪婪与懒惰的理解,但并没有帮助我理解如何在没有糟糕代码的情况下解决我的问题。

TLDR:所需的结果如下所示,将第一个捕获组中的整个字符串与进行匹配。第二个捕获组的内容对我们来说并不重要,除非该组不为空。

shstlldc

shstlldc1#

如果从 * 第一个捕获组 * 中删除可选量词,并将.*?与捕获组一起放入另一个非捕获组中,并使此外部组 * 可选 *,则此方法有效:

^remind me +(?:.*?\b(to|that|about|its|it's)\b *)?(.*)$

See this demo at regex101(我还做了一些小的更改,如添加单词边界,更改变量空间的量词,并删除开始时的非捕获组,这看起来是不必要的)
原因就在how backtracking works。我也遇到过类似的情况,不得不摆弄一下。以你现在的模式,最小的匹配成功是留出可选组。但如果外部组被消耗(捕获组内部已设置)没有理由返回。进一步值得记住的是,外部组的?是一个 * 贪婪 * quantifier和 * 懒惰 * .*?内部。

相关问题