【问题标题】:How can I replace all matches of a string?如何替换字符串的所有匹配项?
【发布时间】:2020-06-23 20:32:36
【问题描述】:

我正在尝试从数组中的多个字符串替换某种自制变量。 稍后我会提示用户要求更换,但在第一步中我只是尝试用“测试”值(“###”)替换它。
哦,我希望它被简化(使用链式函数 - 我只是自己发现的,这就是这里的问题:D)。有人可以帮帮我吗?

到目前为止我得到了什么:

const replaceAll = (obj) => {
    obj.cmds.forEach((element, index, array) => {
        obj.cmds[index] = obj.cmds[index].match(/{.*?}/gmi).map((value) => {
            console.log('valuex', value)
            /*
            // Here the user should be asked for the replacement in the future.
            // const newValue = userPromp(value)
            */
            return obj.cmds[index].split(value).join('###')
        })
    })

    return obj
}

const newObj = replaceAll({
    name: 'ULTRA TEST',
    cmds: [
        'port {port}',
        'port {port} und random {random}',
        'random {random} und value {value}'
    ]
})

console.log(newObj)

【问题讨论】:

  • 你目前的结果是什么?我注意到在本地运行它时您使用 map 但您从未分配它。你可以试试:obj.cmds[index] = obj.cmds[index].match(......
  • MM。那也不返回正确的答案。让我考虑一下。
  • 哦,我看到我忘记了零件。我有这样的本地人:obj.cmds[index] = obj.cmds[index].match(......。但我只得到一个数组中的一个数组作为返回。 :'D

标签: javascript arrays replace


【解决方案1】:

我认为您正在寻找的是这样的: 您可以看到,我没有使用匹配,而是使用替换并传入正则表达式。

replaceAll = (obj) => {
    var m = {};
    obj.cmds.forEach((element, index, array) => {
        obj.cmds[index].match(/{.*?}/gmi).map( value => {
          var r = m[value]
          if (!r) { /* Create Prompt here. */ r = Math.random() * 10 }
          m[value] = r;
        })
        Object.keys(m).map( key => {
          obj.cmds[index] = obj.cmds[index].replace(key, m[key])
        });
    })

    return obj
}
newObj = replaceAll({
    name: 'ULTRA TEST',
    cmds: [
        'port {port}',
        'port {port} und random {random}',
        'random {random} und value {value}'
    ]
})

newObj返回的json是:

{
  "name":"ULTRA TEST",
  "cmds":[
    "port 1",
    "port 1 und random 2",
    "random 2 und value 3"
  ]
}

所以会发生什么,它只会提示用户输入之前在 replaceAll 迭代中未提示的值。

这将完全符合您的要求。

【讨论】:

  • 谢谢。 :) 但我也想向用户显示每个{.*?} 并希望他准确替换每个{.*?}。这就是为什么我如此关注map 功能。 ^^
  • 更准确地说,我想用不同的用户输入替换每个不同的{.*?} 匹配项。
  • @borsTiHD 看看我的编辑。根据您的规格创建它。对于概念证明,它使用随机数字来表示唯一的用户条目。这样您就可以看到它不仅仅是转储###,而是创建了一种基于唯一匹配更新值的机制。
  • 哦,太好了。 :D 正是我想要达到的。非常感谢。
  • @borsTiHD 没问题!
【解决方案2】:

我猜你需要这样的东西

const replaceAll = obj => ({
  ...obj,
  cmds: obj.cmds.map(string => {
    let result = string;
    string.match(/{.*?}/gmi).forEach(template => { 
      // build <replace-string> here
      result = result.split(template).join('$$$'); 
    });
    return result; 
  })
}); 

const newObj = replaceAll({
    name: 'ULTRA TEST',
    cmds: [
        'port {port}',
        'port {port} und random {random}',
        'random {random} und value {value}'
    ]
})

console.log(newObj)

【讨论】:

  • 哦,这就是我最初寻找的东西(仍然更喜欢 Fallenreapers 的回答,因为提示不是要求 twicte 提供相同的“模板”变量)。但我有一个问题。第 2 行 ...obj, 和第 3 行 cmds: 到底在做什么?这是用于 obj 副本并重新分配吗?
  • 这是一种复制对象的方法。 { ...obj } 复制了obj 的所有属性,但是我自己指定了cmds 属性,因为它与源属性不同
  • 哦,太好了,因为我遇到了以下问题...我“替换”了我作为源列表创建的原始 obj。我不止一次地使用这个列表,在一次“替换”之后,我所有的自制 {.*?} 都消失了。同时,我找到了一个使用 JSON 编码/解码的解决方案,用于原始对象的深层副本。
【解决方案3】:

您可以使用内置的替换功能。 String.replace(/regex here/, &lt;string to replace the matched regex&gt;)

所以对于你的情况,我可以这样做:

// take input here
let input = <input from user>

// string to replace with
let replacementString = "###"

for (let cmd of cmds) {
  cmd.replace(/`${input}`/gmi, replacementString);
}

使用for of 而不是forEach,因为您不能在后者中执行break。 (假设您将来可能希望具有逐一替换的功能)。

【讨论】:

  • 感谢您的帮助。用户输入现在对我来说是可选的。仍然没有准备好提示。但是我想替换孔数组中的所有{.*?} 字符串(将来使用不同的用户输入)。 :)
猜你喜欢
  • 2011-08-29
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-16
相关资源
最近更新 更多