我试图解析以下类型的字符串:
[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”也符合这个模式。我怎么能得到所有的比赛回来?
我的猜测是,如果有边界情况,比如额外的或缺失的空格,这种边界更少的表达式也可能是一种选择:
^\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可视化正则表达式:
从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。根据您阅读本文的时间,检查此链接以查看其当前支持。
如果你有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 ] ]
这里有一个没有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 ] ]
如果你能够使用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);