首页 > 解决方案 > 通过正则表达式将字符串的开头(空字符串)捕获为匹配本身

问题描述

''.match(/^/)
// ['']

'ab'.match(/\w/g)
// ['a', 'b']

'ab'.match(/^|\w/g)
// ['', 'b']

如您所见,^被捕获而不是a最新示例中,第一个匹配以某种方式是“字符串的开头”而不是“起始字符本身”。

什么正则表达式将从['', 'a', 'b']字符串中捕获'ab'

标签: javascriptregex

解决方案


发生了什么?

在 PCRE^|\w中匹配行首断言^(空字符串)和单词字符\w( a)。

在 JavaScript 中,在字符串^中的位置满足匹配0,因此它移动到位置1(匹配b),跳过匹配,a因为该位置已经成功匹配。

我必须确认,但似乎大多数正则表达式引擎(JavaScript、Python、Go 等)每个位置只返回一个匹配项。PCRE 将返回您寻找的结果,^|\w因为它似乎返回位置零长度匹配以及字符匹配。


工作正则表达式

您可以使用以下模式来匹配/捕获您正在寻找的结果:

请参阅此处使用的正则表达式(查看右侧的匹配信息)

^(?=(\w)|)|\w

工作代码

下面的代码演示了如何将上述正则表达式的结果转换为数组(exec在循环中使用,然后过滤结果以确保我们在捕获组为 时删除它undefined)。

const regex = /^(?=(\w)|)|\w/g;
const str = `ab`;
let matches=[];

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    matches = matches.concat(m.filter(function(el){return typeof el !== 'undefined'}))
}

console.log(matches)

或使用matchAll如下评论中所述:

const regex = /^(?=(\w)|)|\w/g;
const str = `ab`;
let matches=[];

for (const a of str.matchAll(regex) {
  matches = matches.concat(a.filter(function(el){return typeof el !== 'undefined'}))
}

console.log(matches)

甚至更短:

x = [...'ab'.matchAll(/^(?=(\w)|)|\w/g)].flat().filter(n=>n!==undefined)
console.log(x)


推荐阅读