给定简单模板从示例字符串中提取值

时间:2017-05-25 01:41:38

标签: javascript

我想写一个函数,如:

function extract(template, example){
  //some magic
  return obj;
}

给出如下输入:

var template = "/some/path/{param_one}/{another_param}/etc?arg1={value}";
var example = "/some/path/foo/bar/etc?arg1=baz";

会返回此对象:

{param_one: "foo", another_param: "bar", value: "baz"}

我无法控制模板或示例(例如,我无法将模板更改为具有命名捕获组的正则表达式)。我可以安全地假设给定的示例将与模板匹配。

首先,我能够用这个提取密钥:

var re = /\{(.+?)\}/g;
var match;
do {
    match = re.exec(template)
    if (match) {
        console.log(match[1]);
    }
} while (match);

2 个答案:

答案 0 :(得分:1)

我使用正则表达式并替换来解决:

function extract(template, example){
  //some magic
  var re = /(?:([^\{]*)\{([^\}]*)\})/g;
  var result = example;
  var params = [];
  var match, values, obj = {};
  do {
    match = re.exec(template)
    if (match) {
      result = result.replace(match[1], '|');
      params.push(match[2]);
    }
  } while (match);
  values = result.split('|');
  for(var i=0;i < params.length; i++) {
    obj[params[i]] = values[i+1];
  }
  return obj;
}

首先,它使用params部分和文本部分使用正则表达式,然后用|替换所有文本部分并将存储键存储到params数组。

最后,它循环遍历params数组并匹配从上面分割的值

希望这个帮助

答案 1 :(得分:0)

我会把它分成两部分 - 构建一个模板对象,然后使用该模板对象来解析你的字符串。以下函数buildTemplate(pattern)返回模板对象。然后,您可以使用此对象根据需要解析任意数量的字符串,例如buildTemplate(pattern).parse(string)甚至var parser = buildTemplate(pattern); var parameters = parser.parse(string);

function buildTemplate(pattern) {
    return (function(pattern) {
        function splitString(string) {
            return string.split(/[/?&]+/);
        }

        var glob = {};

        glob.parts = splitString(pattern).map(function(part) {
            var trimmedPart = part.replace(/^\{|\}$/g, '');
            var isLiteral = part.length !== trimmedPart.length + 2;

            return {
                isLiteral: isLiteral,
                value: isLiteral ? part : trimmedPart: 
            };
        });

        glob.parse = function(string) {
            var stringParts = splitString(string);

            if (stringParts.length !== glob.parts.length) {
                return null;
            }

            var params = {};

            for (var i = 0; i < stringParts.length; i++) {
                if (blob.parts[i].isLiteral) {
                    if (blob.parts[i].value !== stringParts[i]) {
                        return null;
                    }
                } else {
                    params[blob.parts[i].value] = stringParts[i];
                }
            }

            return params;
        }

        return glob;
    })(pattern);
}

注意:此代码完全 未经测试 。如果某些内容无效,请告诉我。