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

[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 (pattern),如果pattern具有全局标志g,将以数组形式返回所有匹配项。

例如:

const str = '除了@Emran, @Raju和@Noman,我们都在那里'; console.log ( str.match (/ @ \ w * / g) ); // Will log ["@Emran", "@Raju", "@Noman"]

其他回答

基于Agus的函数,但我更喜欢返回匹配值:

var bob = "> bob <";
function matchAll(str, regex) {
    var res = [];
    var m;
    if (regex.global) {
        while (m = regex.exec(str)) {
            res.push(m[1]);
        }
    } else {
        if (m = regex.exec(str)) {
            res.push(m[1]);
        }
    }
    return res;
}
var Amatch = matchAll(bob, /(&.*?;)/g);
console.log(Amatch);  // yeilds: [>, <]

我们终于开始看到一个内置的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的更多信息,还有一个谷歌开发人员页面。也有填料/垫片可用。

要遍历所有匹配项,可以使用replace函数:

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

s.replace(re, function(match, g1, g2) { console.log(g1, g2); });
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,以便在每次执行时将指针向前移动,这很重要。

Const re = /^\[(?:(.+?):"(.+?)"\s*)+\]$/g Const匹配=[…re.]exec(“[描述:“aoeu”uuid:“123…”)”).entries ()) console.log(匹配) 基本上,这是ES6将exec返回的Iterator转换为常规数组的方法