我试图解析以下类型的字符串:

[key:"val" key2:"val2"]

其中有任意键:“val”对在里面。我想获取键名和值。 对于那些好奇的人,我试图解析任务战士的数据库格式。

这是我的测试字符串:

[description:"aoeu" uuid:"123sth"]

这意味着除了空格之外,任何东西都可以放在键或值中,冒号周围没有空格,值总是在双引号中。

在node中,这是我的输出:

[deuteronomy][gatlin][~]$ node
> var re = /^\[(?:(.+?):"(.+?)"\s*)+\]$/g
> re.exec('[description:"aoeu" uuid:"123sth"]');
[ '[description:"aoeu" uuid:"123sth"]',
  'uuid',
  '123sth',
  index: 0,
  input: '[description:"aoeu" uuid:"123sth"]' ]

但是描述:“aoeu”也符合这个模式。我怎么能得到所有的比赛回来?


当前回答

str.match(/regex/g)

以数组形式返回所有匹配项。

如果出于某种神秘的原因,您需要exec附带的额外信息,作为前面答案的替代方案,您可以使用递归函数来代替循环,如下所示(这看起来也很酷:)。

function findMatches(regex, str, matches = []) {
   const res = regex.exec(str)
   res && matches.push(res) && findMatches(regex, str, matches)
   return matches
}

// Usage
const matches = findMatches(/regex/g, str)

正如前面的评论中所述,在regex定义的末尾加上g,以便在每次执行时将指针向前移动,这很重要。

其他回答

以下是我的回答:

var str = '[me nombre es] : My name is. [Yo puedo] is the right word'; 

var reg = /\[(.*?)\]/g;

var a = str.match(reg);

a = a.toString().replace(/[\[\]]/g, "").split(','));

用这个……

var all_matches = your_string.match(re);
console.log(all_matches)

它将返回一个包含所有匹配项的数组…这很好.... 但是记住它不会考虑分组,它只会返回完整的匹配。

我们终于开始看到一个内置的matchAll函数,请参阅这里的描述和兼容性表。似乎到2020年5月,Chrome、Edge、Firefox和Node.js(12+)都被支持,但IE、Safari和Opera不支持。它似乎是在2018年12月起草的,所以给它一些时间来传播到所有浏览器,但我相信它会到达那里。

内置的matchAll函数很好,因为它返回一个可迭代对象。它还为每个匹配返回捕获组!你可以这样做

// get the letters before and after "o"
let matches = "stackoverflow".matchAll(/(\w)o(\w)/g);

for (match of matches) {
    console.log("letter before:" + match[1]);
    console.log("letter after:" + match[2]);
}

arrayOfAllMatches = [...matches]; // you can also turn the iterable into an array

似乎每个匹配对象都使用与match()相同的格式。因此,每个对象都是匹配和捕获组的数组,以及三个附加属性索引、输入和组。它看起来是这样的:

[<match>, <group1>, <group2>, ..., index: <match offset>, input: <original string>, groups: <named capture groups>]

有关matchAll的更多信息,还有一个谷歌开发人员页面。也有填料/垫片可用。

从ES9开始,现在有一个更简单,更好的方法来获取所有的匹配,以及关于捕获组的信息,以及它们的索引:

const string = 'Mice like to dice rice';
const regex = /.ice/gu;
for(const match of string.matchAll(regex)) {
    console.log(match);
}

// ["mice", index: 0, input: "mice like dice rice", groups: 未定义) // ["dice",索引:13,输入:"老鼠喜欢切米饭", 组:未定义) // ["rice",索引:18,输入:"老鼠喜欢掷骰子。 大米”,组别:未定义

目前支持Chrome, Firefox, Opera。根据您阅读本文的时间,检查此链接以查看其当前支持。

这里有一个没有while循环的一行解决方案。

结果列表中保留该顺序。

潜在的缺点是

它为每个匹配复制正则表达式。 结果与预期的解形式不同。你需要再处理一次。

let re = /\s*([^[:]+):\"([^"]+)"/g
let str = '[description:"aoeu" uuid:"123sth"]'

(str.match(re) || []).map(e => RegExp(re.source, re.flags).exec(e))

[ [ 'description:"aoeu"',
    'description',
    'aoeu',
    index: 0,
    input: 'description:"aoeu"',
    groups: undefined ],
  [ ' uuid:"123sth"',
    'uuid',
    '123sth',
    index: 0,
    input: ' uuid:"123sth"',
    groups: undefined ] ]