替换部分链接

时间:2016-12-01 14:21:44

标签: javascript regex object replace

我有以下链接:

http://example.com/item/[{catalogueId:[0-9]}/key/[{translationId:[a-z]}]]/

在一个对象中我有我需要放在这个链接中的值:

args: {catalogueId: 12, translationId: "en"}

现在我希望链接看起来像这样:

http://example.com/item/12/key/en/

但是当Object看起来像这样:

args: {catalogueId: 12}

链接需要如下所示:

http://example.com/item/12/key/

如果对象为空,则12key也应该不在链接之外。

括号决定链接中显示的内容。 catalogueId括号内的所有内容只有在对象中出现catalogueId时才会显示。

我已经完成了用这个函数替换大括号之间的参数:

for(var key in this.args) {
    var regex = new RegExp('{' + key + '\\b[^}]*}', 'g');
    this.pattern = this.pattern.replace(regex, this.args[key]);
}

但我不知道如何做括号中的部分

1 个答案:

答案 0 :(得分:1)

根据您的最新要求,我更新了解决方案。它不漂亮,但它有效,我认为当你可以删除数组括号并剪切无法进行替换的字符串时,这可能有点过分。

查看评论以获得解释。

const url = 'http://example.com/item/[{catalogueId:[0-9]}/key/[{translationId:[a-z]}]]/'

const REGEX = {
  type: /\[([0-9-a-z]+)\]/g,      // [type]
  brackets: /\[|\]/,              // [|]
  keyType: /\{(\w+)\:([^\}]+)\}/, // {key:[type]}
  placeholder: /\{[^\}]+\}/g      // the entire {placeholder}
}

function test(url, params) {
  // split the url into it's compontent parts
  const parts = url.replace(REGEX.type, '($1)')
    .split(REGEX.brackets)
    .filter(str => str !== '')
  
  const ret = []
  
  for (let ii = 0; ii < parts.length; ii++) {
    // find the key and type
    const matches = parts[ii].match(REGEX.keyType)
    if (matches == null) {
      // no placeholders in this section, just add it to the return
      ret[ii] = parts[ii]
    }
    else {
      const [match, key, type] = matches
      if (typeof params[key] !== 'undefined') {
        // replace the placeholder with the provided value
        ret[ii] = parts[ii].replace(REGEX.placeholder, () => {
          // you could do param type checking here
          return params[key]
        })
      }
      else {
        // this iterations placeholder doesn't match, time to quit
        break
      }
    }
  }
  // if we get through the loop return the url
  return ret.join('')
}

const tests = [
  // it should accept no params
  test(url, {}),
  // it should not include placeholders that are missing
  test(url, {
    catalogueId: 10
  }),
  // it should fill in all placeholders
  test(url, {
    catalogueId: 10,
    translationId: 'test'
  }),
  // it should not skip placeholders
  test(url, {
    translationId: 'test'
  }),
  // it should not error with invalid params
  test(url, {
    invalid: 'param'
  })
]

tests.map(result => console.log(result))
<script src="https://codepen.io/synthet1c/pen/WrQapG.js"></script>

我不得不摆脱数组括号,因为在没有一堆代码的情况下很难让正则表达式与它们一起工作。但是这会通过删除任何不匹配的占位符来做同样的事情。

const test1 = {
  catalogueId: 12, 
  translationId: "en"
}

const test2 = {catalogueId: 12}

const url = 'http://example.com/item/{catalogueId:[0-9]}/key/{translationId:[a-z]}/'

const reg = /\{([^:]+):(\[[^\]]+\])\}/g

const replace = url => components => {
  // replace all the placeholders in the url
  const replaced = url.replace(reg, (_, key, type) => {
    return components[key]
  })
  // clean off any missing values
  const cutIndex = replaced.indexOf('undefined')
  
  return cutIndex < 0
    ? replaced 
    : replaced.substr(0, cutIndex)
}

console.log(
  replace(url)(test1) // 'http://example.com/item/12/key/en/'
)
console.log(
  replace(url)(test2) // 'http://example.com/item/12/key/'
)
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>