如何用Javascript编写一种有效的方法来处理匹配模式?

如何用Javascript编写一种有效的方法来处理匹配模式?,javascript,Javascript,我想生成符合特定模式的字符串。例如,该函数将采用两个参数: function parsePattern(pattern, string) {} 被接受的模式可能是“你好,|你好,%i,你好吗|很高兴见到你”,如果第二个参数以这种方式设置为“John” parsePattern('(hello|hi), %i, (how are you|nice to see you)', 'John') 我希望输出具有所有可能的组合: 'hello, John, how are you' 'hello,

我想生成符合特定模式的字符串。例如,该函数将采用两个参数:

function parsePattern(pattern, string) {}
被接受的模式可能是“你好,|你好,%i,你好吗|很高兴见到你”,如果第二个参数以这种方式设置为“John”

parsePattern('(hello|hi), %i, (how are you|nice to see you)', 'John')
我希望输出具有所有可能的组合:

 'hello, John, how are you'
 'hello, John, nice to see you'
 'hi, John, how are you'
 'hi, John, nice to see you'

实现这一点的最佳方法是什么?

您正在寻找一种与正则表达式通常使用的相反的方法,因此不可能使用更通用的正则表达式模式,如\w+。但是,如果您只是希望为A | B类型的模式生成结果,如您的示例中所示,那么下面的一些代码将实现这一点。这利用了给定的笛卡尔积函数。当然,你可以用你自己的来代替这些

JSFiddle:


到目前为止您尝试了什么?基本上您只想解析2个参数,然后只要匹配结果字符串是否匹配第一个参数的模式。然后使用替换和匹配。
String.prototype.formatUnicorn = String.prototype.formatUnicorn ||
  function () {
  "use strict";
  var str = this.toString();
  if (arguments.length) {
    var t = typeof arguments[0];
    var key;
    var args = ("string" === t || "number" === t) ?
        Array.prototype.slice.call(arguments)
    : arguments[0];

    for (key in args) {
      str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);
    }
  }

  return str;
};

function cartesianProduct(arr) {
  return arr.reduce(function (a, b) {
    return a.map(function (x) {
      return b.map(function (y) {
        return x.concat([y]);
      })
    }).reduce(function (a, b) { return a.concat(b) }, [])
  }, [[]])
}

function parsePattern(pattern, str) {
  var regex = /\(([^|()]+\|)*[^|()]+\)/g;
  var results = [];

  var matches = pattern.match(regex);

  // replace input string match groups with format strings
  matches.forEach(function (el, idx) {
    pattern = pattern.replace(el, '{' + (idx + 1) + '}');
  });

  // split matches into parts
  var matchesSplit = [];

  matches.forEach(function (el, idx) {
    matchesSplit[idx] = el.replace(/[()]/g, '').split('|');
  });

  // generate result strings
  matchesSplit.splice(0, 0, [str]);

  cartesianProduct(matchesSplit).forEach(function (el) {
    results.push(pattern.formatUnicorn(el));
  });

  return results;
}