JavaScript正则表达式重复(子组

时间:2014-03-19 15:42:40

标签: javascript regex

是否可以使用正则表达式从单个调用返回所有重复和匹配的子组?

例如,我有一个像:

这样的字符串
{{token id=foo1 class=foo2 attr1=foo3}}

属性数量(即idclassattr1)未定义且可以是任何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"]

它似乎只匹配最后一组;有没有办法获得所有其他“属性”(argid)?

注意:该示例说明了对单个字符串的匹配,但搜索的模式位于一个更大的字符串中,可能包含许多匹配项。因此,^$无法使用。

2 个答案:

答案 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);

jsFiddle

一个疯狂的想法是使用正则表达式并替换以将代码转换为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 '';
 }

REY

答案 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"]

现场演示:http://jsfiddle.net/HYW72/1/