在一次替换调用中替换多个字符

Posted

技术标签:

【中文标题】在一次替换调用中替换多个字符【英文标题】:Replace multiple characters in one replace call 【发布时间】:2013-05-10 17:30:21 【问题描述】:

我需要将“_”的每个实例替换为空格,将“#”的每个实例替换为空/空。

var string = '#Please send_an_information_pack_to_the_following_address:';

我试过了:

string.replace('#','').replace('_', ' ');

我真的不喜欢这样的链接命令。有没有其他方法可以做到这一点?

【问题讨论】:

查看这个问题的答案:***.com/questions/7072330/… 我打赌你未来的自己会后悔你的决定,阅读链式命令比阅读丑陋的正则表达式要清楚得多 @EduardoMolteni 我不同意 - 我认为了解正则表达式的工作原理很重要,更不用说使用 replace 方法来实现我的 OQ,除非您创建一个链接选项,否则您仍然需要正则表达式作为链接选项无论如何自定义原型扩展 @DeweyOx 阅读 OP 这不是答案,而且已经回答了很多次,请不要乱扔旧问题和错误答案 【参考方案1】:

使用 OR 运算符 (|):

var str = '#this #is__ __#a test###__';
str.replace(/#|_/g,''); // result: "this is a test"

你也可以使用字符类:

str.replace(/[#_]/g,'');

Fiddle

如果你想用一个东西替换散列,用另一个东西替换下划线,那么你只需要链接。但是,您可以添加一个原型:

String.prototype.allReplace = function(obj) 
    var retStr = this;
    for (var x in obj) 
        retStr = retStr.replace(new RegExp(x, 'g'), obj[x]);
    
    return retStr;
;

console.log('aabbaabbcc'.allReplace('a': 'h', 'b': 'o'));
// console.log 'hhoohhoocc';

为什么不链呢?我认为这没有什么问题。

【讨论】:

这很酷,但我需要用不为空的空格替换下划线,我可以这样做吗? 这么想,但你仍然帮助我理解了替换表达式如何更好地工作:) 您的原型不工作?你能提供一个关于小提琴的例子吗,我不断收到错误 #|_ 的另一个选项是[#_],您不妨使用+ 匹配任何连续匹配以提高性能 很酷,谢谢...如果需要替换空格和其他符号str.replace(/[+ -]/g,'');,只需将空格放在中间即可。【参考方案2】:

如果你想替换多个字符,你可以调用String.prototype.replace(),替换参数是每次匹配调用的函数。您只需要一个表示您将在该函数中使用的字符映射的对象。

例如,如果您想将a 替换为x,将b 替换为y,将c 替换为z,您可以执行以下操作:

var chars = 'a':'x','b':'y','c':'z';
var s = '234abc567bbbbac';
s = s.replace(/[abc]/g, m => chars[m]);
console.log(s);

输出234xyz567yyyyxz

【讨论】:

由于您使用 ES6(箭头函数),因此您还应该在此处将 var 替换为 const。扩展浏览器支持的替代方案:var s ='234abc567bbbbac'; s = s.replace(/[abc]/g, function(m) return 'a':'x','b':'y','c':'z'[m]; ); console.log(s); @FelixGeenen 1. 你扼杀了可移植性 2. 如果你选择重新定义 chars 或 s,你会得到一个运行时错误,这会扼杀它的健壮性, 3. 没有保证 s 免受突变并重新绑定,而不是纯粹的意识形态。很高兴看到这个 sn-p 在双击/cscript/wscript 时仍然可以在新安装的 windows98 中工作:var chars = a:'1', b:'2', c:'3'; var s = '123abc123'; var u = s.replace(/[abc]/g, function(m) return chars[m]; ); WScript.echo(u); 这真是太好了。谢谢。您使用对象执行 or 语句的部分是什么。您是否有文档或参考资料来解释这一点。相当不错的用例。 您可以在一行中替换多个:string.replace(/[#_]/g, x => ('_': ' ', '#': '')[x]); 注意对象周围的() — 没有它们会出错。 @wilcro 我认为[x] 应该在括号内,('_': ' ', '#': ''[x]) 而不是('_': ' ', '#': '')[x]【参考方案3】:

链接很酷,为什么要放弃它?

无论如何,这是一次替换的另一种选择:

string.replace(/#|_/g,function(match) return (match=="#")?"":" ";)

如果 match=="#" 则替换将选择 "",否则将选择 ""。

[更新] 对于更通用的解决方案,您可以将替换字符串存储在一个对象中:

var replaceChars= "#":"" , "_":" " ;
string.replace(/#|_/g,function(match) return replaceChars[match];)

【讨论】:

采取额外的步骤:var regex = new RegExp( Object.keys(replaceChars).join("|"), "g");string.replace(regex,function(match) return replaceChars[match];) 这使得修改 replaceChars 更容易。 @RozzA 谢谢。 Object.keys 在当时还不是主流。 我完全忘记了替换第二个参数的替换功能选项,帮助我记住:)【参考方案4】:

在正则表达式上指定/g(全局)标志以替换所有匹配项,而不仅仅是第一个:

string.replace(/_/g, ' ').replace(/#/g, '')

要用一种东西替换一个字符,用另一种东西替换一个不同的字符,需要两次单独调用replace 是不可能的。你可以像 Doorknob 那样将它抽象成一个函数,尽管我可能会让它使用一个带有旧/新的对象作为键/值对,而不是一个平面数组。

【讨论】:

如何也包含哈希?【参考方案5】:

我不知道这是否有多大帮助,但我想从我的字符串中删除 <b></b>

所以我用了

mystring.replace('<b>',' ').replace('</b>','');

所以基本上,如果您希望减少有限数量的字符并且不浪费时间,这将很有用。

【讨论】:

【参考方案6】:

你可以试试这个:

str.replace(/[.#]/g, 'replacechar');

这将用你的替换字符替换 .,- 和 # !

【讨论】:

这个答案已经提供,不处理用其他字符替换不同的字符,请参阅 OP。【参考方案7】:

第二次更新

我开发了以下功能用于生产,也许它可以帮助其他人。它基本上是原生的replaceAll javascript函数的循环,它不使用正则表达式:

function replaceMultiple(text, characters)
  for (const [i, each] of characters.entries()) 
    const previousChar = Object.keys(each);
    const newChar = Object.values(each);

    text = text.replaceAll(previousChar, newChar);
    
  
return text

用法很简单。以下是使用 OP 示例的样子:


const text = '#Please send_an_information_pack_to_the_following_address:';
const characters = [
    
    "#":""
    ,
   
    "_":" "
    ,
]

const result = replaceMultiple(text, characters);

console.log(result); //'Please send an information pack to the following address:'

更新

您现在可以原生使用replaceAll。

过时的答案

这是另一个使用字符串原型的版本。享受吧!

String.prototype.replaceAll = function(obj) 
    let finalString = '';
    let word = this;
    for (let each of word)
        for (const o in obj)
            const value = obj[o];
            if (each == o)
                each = value;
            
        
        finalString += each;
    
    
    return finalString;
;

'abc'.replaceAll('a':'x', 'b':'y'); //"xyc"

【讨论】:

这是最糟糕的答案。您不应该自己覆盖官方规范中接受的功能。 tc39.es/ecma262/multipage/… @Daniel 你是对的。当我在 2019 年写这篇文章时,“replaceAll”还不可用。感谢您的提醒。【参考方案8】:

请尝试:

替换多个字符串

var str = "http://www.abc.xyz.com"; str = str.replace(/http:|www|.com/g, ''); //str is "//.abc.xyz"

替换多个字符

var str = "a.b.c.d,e,f,g,h"; str = str.replace(/[.,]/g, ''); //str is "abcdefgh";

祝你好运!

【讨论】:

我找到的最佳解决方案!【参考方案9】:

你也可以试试这个:

function replaceStr(str, find, replace) 
    for (var i = 0; i < find.length; i++) 
        str = str.replace(new RegExp(find[i], 'gi'), replace[i]);
    
    return str;


var text = "#here_is_the_one#";
var find = ["#","_"];
var replace = ['',' '];
text = replaceStr(text, find, replace);
console.log(text);

find 是要查找的文本,replace 是要替换的文本

这将替换不区分大小写的字符。要做其他方式只需根据需要更改正则表达式标志。例如:对于区分大小写的替换:

new RegExp(find[i], 'g')

【讨论】:

【参考方案10】:

可以用简单的正则表达式替换多个子字符串。 例如,我们要将数字(123) 456-7890变成1234567890,我们可以这样做。

var a = '(123) 456-7890';
var b = a.replace(/[() -]/g, '');
console.log(b); // results 1234567890

我们可以在[]之间传递要替换的子字符串,而要使用的字符串应该作为第二个参数传递给replace函数。

【讨论】:

【参考方案11】:

这是一种不使用 RegEx 的简单方法。您可以根据需要制作原型和/或缓存内容。

// Example: translate( 'faded', 'abcdef', '123456' ) returns '61454'
function translate( s, sFrom, sTo )
    for ( var out = '', i = 0; i < s.length; i++ )
        out += sTo.charAt( sFrom.indexOf( s.charAt(i) ));
    
    return out;

【讨论】:

我知道你没有说明,但是使用正则表达式不是更优雅吗? str.replace(/#|_/g,'') @ShannonHochkins 当然!我并不是要抨击 RegEx。我只是展示另一种选择。正则表达式并不总是直观的,它适合“作为一把锤子,把每个问题都当作钉子”来使用。再加上看看其他答案,作为一个可重用的函数,这个函数并不长,而且参数很容易理解。就我个人而言,我会在这里用一个简短的 RegEx 来回答这个问题,如果你只是在寻找一个你不介意不完全理解的快速插入式 sn-p,这是有道理的。 好吧,如果你需要翻译一个字符(à la sed y 命令或à la Unix tr),这似乎喜欢正确的答案。【参考方案12】:

您也可以将 RegExp 对象传递给 replace 方法,例如

var regexUnderscore = new RegExp("_", "g"); //indicates global match
var regexHash = new RegExp("#", "g");

string.replace(regexHash, "").replace(regexUnderscore, " ");

Javascript RegExp

【讨论】:

OP 不想链接 replace 调用 - 这无助于避免这种情况。【参考方案13】:

yourstring = '#请发送_an_information_pack_to_the_following_address:';

将“#”替换为“”,将“_”替换为空格

var newstring1 = yourstring.split('#').join('');
var newstring2 = newstring1.split('_').join(' ');

newstring2 是你的结果

【讨论】:

你的答案没有使用 jQuery,也没有遵循 OP,'#this #is__ #a test###'.split( '_').join(' ') 不起作用,因为你会得到更多的空白 @ShannonHochkins 还要添加多少空格? 看看我的例子,当空格前有一个下划线,或者两个下划线时,你会得到多个空格。 @ShannonHochkins 提问者处理字符串 '#Please send_an_information_pack_to_the_following_address:';这里没有空间。为什么我会想到它。想想,为什么只有空间,很多其他的事情可能会发生。 我建议你重新阅读OP,我是原始海报,你可以在我的第一个变量var str = '#this #is__ __#a test###__';中清楚地看到这个字符串中有多个空格。【参考方案14】:

对于什么都没有,tckmn's answer 是最好的。

如果您需要替换为与匹配项对应的特定字符串,这是 Voicu 和 Christophe 的答案的变体,可避免重复匹配的内容,这样您就不必记住在两个地方添加新匹配项:

const replacements = 
  '’': "'",
  '“': '"',
  '”': '"',
  '—': '---',
  '–': '--',
;
const replacement_regex = new RegExp(Object
  .keys(replacements)
  // escape any regex literals found in the replacement keys:
  .map(e => e.replace(/[.*+?^$()|[\]\\]/g, '\\$&'))
  .join('|')
, 'g');
return text.replace(replacement_regex, e => replacements[e]);

【讨论】:

【参考方案15】:

这适用于意第绪语其他角色,例如 NEKUDES

var string = "נׂקֹוַדֹּוֶת";


var string_norm = string.replace(/[ְֱֲֳִֵֶַָֹֹּׁׂ]/g, '');
document.getElementById("demo").innerhtml = (string_norm);

【讨论】:

【参考方案16】:

String.prototype.replaceAll=function(obj,keydata='key')
 const keys=keydata.split('key');
return Object.entries(obj).reduce((a,[key,val])=> a.replace(new RegExp(`$keys[0]$key$keys[1]`,'g'),val),this)


const data='hids dv sdc sd yathin ok'
console.log(data.replaceAll(yathin:12,ok:'hi','key'))

【讨论】:

您好,欢迎来到 ***。也许您可以添加一些关于您的代码在做什么以及为什么要这样做的解释?此外,您可能想要清理您的答案中的一些重复代码(未格式化)。【参考方案17】:

不知道为什么还没有人提供这个解决方案,但我发现它工作得很好:

var string = '#Please send_an_information_pack_to_the_following_address:'
var placeholders = [
    "_": " ",
    "#": ""
]

for(var placeholder in placeholders)
    while(string.indexOf(placeholder) > -1) 
        string = string.replace(placeholder, placeholders[placeholder])
    

您可以根据需要添加任何占位符,而无需更新您的函数。简单!

【讨论】:

因为与其他解决方案相比过于复杂 不使用正则表达式,不使用链接,使用每个人都能理解的简单循环,当输入改变时不需要更新函数,允许占位符的抽象。新的(和老的)开发人员将立即理解代码,不需要抽象语言特性的深奥知识。我告诉你,这是提供的最简单、最灵活的解决方案。【参考方案18】:

这是一个使用“减少”多重替换函数的“安全 HTML”函数(该函数将每个替换应用于整个字符串,因此替换之间的依赖性很重要)。

// Test:
document.write(SafeHTML('<div>\n\
    x</div>'));

function SafeHTML(str)
    
    const replacements = [
        '&':'&amp;',
        '<':'&lt;',
        '>':'&gt;',
        '"':'&quot;',
        "'":'&apos;',
        '`':'&grave;',
        '\n':'<br>',
        ' ':'&nbsp;'
        ];
    return replaceManyStr(replacements,str);
     // HTMLToSafeHTML

function replaceManyStr(replacements,str)
    
    return replacements.reduce((accum,t) => accum.replace(new RegExp(Object.keys(t)[0],'g'),t[Object.keys(t)[0]]),str);
    

【讨论】:

感谢您的帖子,但与接受的答案相比,它相当广泛 问题的答案是单行函数。怎么这么“广泛”?使用户输入安全就是一个重要的例子。你太挑剔了。 'reduce' 是一个非常有用的技术,你应该知道。 我说你的答案太广泛了,代码多了,反正你在使用正则表达式,只是让过程太复杂,不知道你认为你的答案与任何答案相比如何减少这些答案... 我的答案是“减少”答案,因为它使用了 Array.prototype.reduce 函数。更简短的答案可能使用字符串而不是属性键,利用“安全 HTML”功能仅适用于替换单个字符的事实。我挑战你想出一个更优雅的答案,而不是像这样在公共场合粗鲁地抱怨。 其实我说了谢谢,也给了你批评,你接受了,决定写一些讽刺的东西,如果我们要从函数式方法开始执行,而不是像我们应该的原型链式方法,然后是更简单的东西,例如:jsfiddle.net/shannonhochkins/xsm9j610/21

以上是关于在一次替换调用中替换多个字符的主要内容,如果未能解决你的问题,请参考以下文章

链式 REPLACE 函数在一次查询执行时仅替换一个值

C ++一次替换字符串中的多个字符串

presto替换多个字符

一次替换多个字符串

Java一次替换字符串中的多个不同子字符串(或以最有效的方式)

java 字符串替换函数replaceAll 一次同时替换多个字符串