不区分大小写替换所有

123

我正在寻找一个不区分大小写的替换函数的实现。例如,它应该像这样工作:

'This iS IIS'.replaceAll('is', 'as');

结果应该是:

'Thas as Ias'
任何想法吗? 更新: 最好能够与变量一起使用。
var searchStr = 'is';
'This iS IIS'.replaceAll(searchStr, 'as');
9个回答

206

尝试使用正则表达式:

'This iS IIS'.replace(/is/ig, 'as');

工作示例:http://jsfiddle.net/9xAse/

例如:
使用RegExp对象:

var searchMask = "is";
var regEx = new RegExp(searchMask, "ig");
var replaceMask = "as";

var result = 'This iS IIS'.replace(regEx, replaceMask);

6
好的!但是如何使用变量替换 .replace(searchMask, replaceMask) - Sergey Metlov
@DOTNET忍者:已更新帖子,并提供了一个示例。 - Chandu
1
如果可以的话,我会给第二个代码示例两个赞,因为它实际上解释了正在发生的事情。 - Chris Marisic
15
警告:当有一个具有正则表达式含义的字符时,此答案会导致混乱。请参考Benjamin Fleming的答案以获得正确的方法。 - FlorianB
非常感谢,伙计!我一直在尝试直接使用字符串。 - Saurabh Prajapati
答案可以,但是使用正则表达式的性能非常差,与经典的替换相比。所以能看到一个性能良好的变体会很棒,而不仅仅是一个简短的解决方案。 - undefined

77
String.prototype.replaceAll = function(strReplace, strWith) {
    // See https://dev59.com/AXA65IYBdhLWcg3w7DT8#3561711
    var esc = strReplace.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    var reg = new RegExp(esc, 'ig');
    return this.replace(reg, strWith);
};

这个实现完全按照你提供的例子。

'This iS IIS'.replaceAll('is', 'as');

返回

'Thas as Ias'

2
这确实是正确的解决方案。当存在具有正则表达式含义的字符时,Chandu的答案会造成混乱。 - FlorianB
这也可以处理像这样的情况:txt.replaceAll("(test12)", "")。 - user1400290
迄今为止最好的解决方案。运行得很好。谢谢Ben。 - Ste

13

当您使用正则表达式解决方案时,如果您的替换字符串包含例如"?",那么您可能会遇到问题。因此,您必须转义所有正则表达式字符或者使用例如:

当你使用正则表达式解决方案时,如果你的替换字符串中包含例如"?"字符,那么你可能会遇到问题。所以你需要转义所有正则表达式特殊字符,或者使用例如:

String.replacei = String.prototype.replacei = function (rep, rby) {
    var pos = this.toLowerCase().indexOf(rep.toLowerCase());
    return pos == -1 ? this : this.substr(0, pos) + rby + this.substr(pos + rep.length);
};

这不会改变字符串中所有“is”的出现次数。因此,您可以在函数中编写while循环。


这也比正则表达式解决方案快两倍..请参见https://jsperf.com/replace-all-case-insenstive/1 - kofifus
1
这仅替换一次。 - StefansArya

6
这是根据Paul的回答进行的改进,正则表达式与非正则表达式之间存在性能差距。
比较使用的正则表达式代码来自Benjamin Fleming的回答。 JSPerf 区分大小写 正则表达式:66,542次/秒 非正则表达式:178,636次/秒(split-join) 不区分大小写 正则表达式:37,837次/秒 非正则表达式:12,566次/秒(indexOf-substr)

String.prototype.replaces = function(str, replace, incaseSensitive) {
    if(!incaseSensitive){
        return this.split(str).join(replace);
    } else { 
        // Replace this part with regex for more performance

        var strLower = this.toLowerCase();
        var findLower = String(str).toLowerCase();
        var strTemp = this.toString();

        var pos = strLower.length;
        while((pos = strLower.lastIndexOf(findLower, pos)) != -1){
            strTemp = strTemp.substr(0, pos) + replace + strTemp.substr(pos + findLower.length);
            pos--;
        }
        return strTemp;
    }
};

// Example
var text = "A Quick Dog Jumps Over The Lazy Dog";
console.log(text.replaces("dog", "Cat", true));


警告:如果str字符串位于输入字符串的开头,则会导致无限循环。 - Evariste
看起来好像有人已经在下面发布了一行修复代码作为新答案,实际上我很乐意接受社区对我的回答的编辑。 - StefansArya

2
注意,上面提供的答案中存在一个错误。如果您的原始字符串以替换字符串开头,那么会进入无限循环。
String.prototype.replaces = function(str, replace, incaseSensitive) {
    if(!incaseSensitive){
        return this.split(str).join(replace);
    } else { 
        // Replace this part with regex for more performance

        var strLower = this.toLowerCase();
        var findLower = String(str).toLowerCase();
        var strTemp = this.toString();

        var pos = strLower.length;
        while((pos = strLower.lastIndexOf(findLower, pos)) != -1){
            strTemp = strTemp.substr(0, pos) + replace + strTemp.substr(pos + findLower.length);
            if (pos == 0) break; // Fixes bug
            pos--;
        }
        return strTemp;
    }
};

// Example
var text = "Dog Jumps Over The Lazy Dog";
console.log(text.replaces("dog", "Cat", true));

1
使用正则表达式。
'This iS IIS'.replace(/is/ig, 'as')

0

不敏感的ReplaceAll:12 053 033被1秒替换
用ReplaceAll("狗跳过懒惰的狗", "狗", "猫")

例子:

function ReplaceAll(base,told,tnew) { // replace insensitive
  if (told=="") {return base;}
  var u=base.toLowerCase();
  var t=told.toLowerCase();
  var ss=""; var p=-1; var i=0;
  p=u.indexOf(t);
  if (p>-1) {
    let mLen=told.length;
    while (p>=0) {
      ss+=base.substr(0,p)+tnew;
      i=p+mLen;
      base=base.substr(i);
      u=u.substr(i);
      p=u.indexOf(t);
    }
    ss+=base; //fix bug
    return ss;
  }
  return base;
}    
/*Test:
    
    function loopThrough() {
             for (let i = 0; i < 60000000; i++) {
               let s=ReplaceAll("Dog Jumps Over The Lazy Dog","dog","Cat");
             }
          }
    
    $(document).ready(function(){
      $("button").click(function(){
          //alert(ReplaceAll("Dog Jumps Over The Lazy Dog","dog", "Cat"));
          
          document.getElementById("demo").innerHTML = '...';
          let startTime = new Date();
          loopThrough();
          let endTime = new Date();
          let timeElapsed = endTime - startTime;
          document.getElementById("demo").innerHTML =  "elapsed times: " + timeElapsed + " milliseconds.";
*/

这个有什么比被接受的答案更好的地方吗? - 0stone0
试一下我展示的例子,可能在正则表达式的接受答案中不能正确工作。 - Jan Tungli
试试我展示的例子,可能在正则表达式的接受答案中无法正确工作。 - undefined
'This Beta=? iS IIS'.replace(/beta=?/ig, 'BETA=1') 的结果是不正确的值 - Jan Tungli

0
如果你因为性能问题而想避免使用正则表达式,你可以考虑实现一个自定义函数。这个自定义函数可以循环遍历字符串,无论大小写,找到匹配项并进行替换。但要注意,这种方法可能不如使用精心设计的正则表达式高效,特别是对于大字符串或复杂的替换模式。
function replaceCaseInsensitive(str, find, replace) {
    let result = "";
    let findLower = find.toLowerCase();
    let index = 0;

    while (index < str.length) {
        if (str.substring(index).toLowerCase().startsWith(findLower)) {
            result += replace;
            index += find.length;
        } else {
            result += str[index];
            index++;
        }
    }

    return result;
}

// Example usage
let originalString = "Hello World";
let newString = replaceCaseInsensitive(originalString, "world", "Universe");
console.log(newString); // Output: Hello Universe

-2

我推荐使用 php.js 中的 str_ireplace 函数,它甚至可以替换数组中的字符串。


4
使用第三方库来完成这么简单的任务可能有些过度杀伤力。 - Balázs Vincze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接