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

[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”也符合这个模式。我怎么能得到所有的比赛回来?


当前回答

这是一个解

var s = '[description:"aoeu" uuid:"123sth"]';

var re = /\s*([^[:]+):\"([^"]+)"/g;
var m;
while (m = re.exec(s)) {
  console.log(m[1], m[2]);
}

这是基于lawnsea的答案,但更简短。

注意,必须设置' g'标志,以便在多个调用之间向前移动内部指针。

其他回答

如果你有ES9

(意思是如果你的系统:Chrome, Node.js, Firefox等支持Ecmascript 2019或更高版本) 使用新的yourString。matchAll(/your-regex/g)。

如果你没有ES9

如果您使用的是较旧的系统,这里有一个简单的复制和粘贴函数

function findAll(regexPattern, sourceString) {
    let output = []
    let match
    // auto-add global flag while keeping others as-is
    let regexPatternWithGlobal = RegExp(regexPattern,[...new Set("g"+regexPattern.flags)].join(""))
    while (match = regexPatternWithGlobal.exec(sourceString)) {
        // get rid of the string copy
        delete match.input
        // store the match data
        output.push(match)
    } 
    return output
}

使用示例:

console.log(   findAll(/blah/g,'blah1 blah2')   ) 

输出:

[ [ 'blah', index: 0 ], [ 'blah', index: 6 ] ]

我的猜测是,如果有边界情况,比如额外的或缺失的空格,这种边界更少的表达式也可能是一种选择:

^\s*\[\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*\]\s*$

如果你想探索/简化/修改这个表达式,它已经被 在右上方的面板上有解释 regex101.com。如果你愿意,你可以 还能在这看吗 链接,如何匹配 对照一些样本输入。


Test

const regex = /^\s*\[\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*\]\s*$/gm; const str = `[description:"aoeu" uuid:"123sth"] [description : "aoeu" uuid: "123sth"] [ description : "aoeu" uuid: "123sth" ] [ description : "aoeu" uuid : "123sth" ] [ description : "aoeu"uuid : "123sth" ] `; let m; while ((m = regex.exec(str)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === regex.lastIndex) { regex.lastIndex++; } // The result can be accessed through the `m`-variable. m.forEach((match, groupIndex) => { console.log(`Found match, group ${groupIndex}: ${match}`); }); }

RegEx电路

jex。Im可视化正则表达式:

如果你能够使用matchAll,这里有一个技巧:

数组中。From有一个“选择器”参数,这样你就不会得到一个尴尬的“匹配”结果数组,你可以把它投射到你真正需要的东西上:

Array.from(str.matchAll(regexp), m => m[0]);

如果你已经命名了组。(/(?<firstname>[a-z][a-z] +)/g)你可以这样做:

Array.from(str.matchAll(regexp), m => m.groups.firstName);

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

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

s.replace(re, function(match, g1, g2) { console.log(g1, g2); });

从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。根据您阅读本文的时间,检查此链接以查看其当前支持。