是否可以使用正则表达式从单个调用返回所有重复和匹配的子组?
例如,我有一个像:
这样的字符串{{token id=foo1 class=foo2 attr1=foo3}}
属性数量(即id
,class
,attr1
)未定义且可以是任何key=value
对。
例如,在moement,我有以下regexp and output
var pattern = /\{{([\w\.]+)(?:\s+(\w+)=(?:("(?:[^"]*)")|([\w\.]+)))*\}\}/;
var str = '{{token arg=1 id=2 class=3}}';
var matches = str.match(pattern);
// -> ["{{token arg=1 id=2 class=3}}", "token", "class", undefined, "3"]
它似乎只匹配最后一组;有没有办法获得所有其他“属性”(arg
和id
)?
注意:该示例说明了对单个字符串的匹配,但搜索的模式位于一个更大的字符串中,可能包含许多匹配项。因此,^
和$
无法使用。
答案 0 :(得分:1)
这在一个正则表达式中是不可能的。 JavaScript Regex只会返回最后一个匹配的组,这正是您的问题所在。我有一段时间似乎有这个问题:Regex only capturing last instance of capture group in match。你可以在.Net中使用它,但这可能不是你需要的。
我确信你可以弄清楚如何在正则表达式中执行此操作,并从第二组中吐出参数。
\{\{(\w+)\s+(.*?)\}\}
这里有一些javaScript代码向您展示它是如何完成的:
var input = $('#input').text();
var regex = /\{\{(\w+)\s*(.*?)\}\}/g;
var match;
var attribs;
var kvp;
var output = '';
while ((match = regex.exec(input)) != null) {
output += match[1] += ': <br/>';
if (match.length > 2) {
attribs = match[2].split(/\s+/g);
for (var i = 0; i < attribs.length; i++) {
kvp = attribs[i].split(/\s*=\s*/);
output += ' - ' + kvp[0] + ' = ' + kvp[1] + '<br/>';
}
}
}
$('#output').html(output);
一个疯狂的想法是使用正则表达式并替换以将代码转换为json,然后使用JSON.parse进行解码。我知道以下是这个想法的开始。
/[\s\S]*?(?:\{\{(\w+)\s+(.*?)\}\}|$)/g.replace(input, doReplace);
function doReplace ($1, $2, $3) {
if ($2) {
return "'" + $2 + "': {" +
$3.replace(/\s+/g, ',')
.replace(/=/g, ':')
.replace(/(\w+)(?=:)/g, "'$1'") + '};\n';
}
return '';
}
答案 1 :(得分:0)
你可以这样做:
var s = "{{token id=foo1 class=foo2 attr1=foo3 hi=we}} hiwe=wef";
var matches = s.match(/(\w+(?==\w+)|(?!==\w+)\w+)(?!\{\{)(?!.*token)(?=.*}})/g);
matches.splice(0,1);
for (var i = 0; i < matches.length; i++) {
alert(matches[i]);
}
正则表达式为/(\w+(?==\w+)|(?!==\w+)\w+)(?!\{\{)(?!.*token)(?=.*}})/g
(使用全局修饰符g
来匹配所有属性)
数组将如下所示:
["id","foo1","class","foo2","attr1","foo3","hi","we"]