不带正则表达式的JavaScript中不区分大小写的字符串替换全部

时间:2015-04-21 20:36:10

标签: javascript string replace case-insensitive

我想在JavaScript中使用不区分大小写的字符串replace-all而不使用正则表达式(或者在调用replace方法时使用正则表达式字符串)。我无法找到问题或答案,但如果我错过了,请将其链接。

例如,在:

中用'x'替换'abc'

Find aBc&def stuff ABCabc变为Find x&def stuff xx

结果应该保留未更换部分的原始情况。

字符串中可能包含特殊字符,所以这就是为什么我要避免使用正则表达式。我的特殊问题可以通过正则表达式解决,但我有兴趣完全避免它。

有几个问题和答案使用正则表达式,并包括特殊字符的处理。特别是,bobince在这里的回答https://stackoverflow.com/a/280837/292060描述了如果不了解或采取原始字符串中的特定条件,它可能是不可能的。

我认为它将涉及循环和indexOf,并遍历原始字符串,构建结果。

为了这个问题,让我们说性能不是主要问题。例如,循环字符可以。

现有的一些问题包括所有答案的正则表达式:

修改
从一些答案,一些澄清 - 我最初没有说明这些,但它们是典型的搜索/替换行为:

可以替换为相同的字符串,例如,将'abc'替换为'Abc',比如修复名称的标题大小写。

不应重新检查替换,例如,将“ab”替换为“abc”应该有效。例如,在abcc中将'abc'替换为'ab'会变为abc而不是ab

我认为这些归结为更换应该完成,然后在字符串中移动,而不是“回头看”。

修改 以下是一些仅供记录的测试用例。我没有进入空字符串等,这可能也应该进行测试。 https://jsfiddle.net/k364st09/1/

("Find aBc&def abc", "abc", "xy")   - Find xy&def xy - general test
("Find aBc&def abc", "abc", "ABC")  - Find ABC&def ABC - replace same test, avoid infinite loop
("Find aBcc&def abc", "abc", "ab")  - Find abc&def ab - "move on" avoid double checking (fails if abcc becomes ab)
("abc def", "abc", "xy")            - xy def - Don't drop last characters.
("abcc def", "abc", "xy")           - xyc def  - Just a mix of "move on" and "don't drop last".

5 个答案:

答案 0 :(得分:2)

  1. 以空字符串开头并复制原始字符串。
  2. 在副本中查找要替换的字符串的索引(将它们设置为小写会使搜索不区分大小写)。
  3. 如果副本中没有,请跳至步骤7.
  4. 将所有内容从副本添加到索引,再加上替换。
  5. 将副本修剪到您要替换的部分之后的所有内容。
  6. 返回第2步。
  7. 添加副本左侧的内容。
  8. 为了好玩,我创建了一个交互式版本,您可以在其中查看正则表达式和indexOf的结果,以查看转义正则表达式是否会破坏任何内容。用于转义我从jQuery UI获取的正则表达式的方法。如果您将其包含在页面中,则可以使用$.ui.autocomplete.escapeRegex找到它。否则,它的功能非常小。

    这里是非正则表达式函数,但由于交互式部分添加了更多代码,因此我默认隐藏了完整的代码段。

    function insensitiveReplaceAll(original, find, replace) {
      var str = "",
        remainder = original,
        lowFind = find.toLowerCase(),
        idx;
    
      while ((idx = remainder.toLowerCase().indexOf(lowFind)) !== -1) {
        str += remainder.substr(0, idx) + replace;
    
        remainder = remainder.substr(idx + find.length);
      }
    
      return str + remainder;
    }
    
    // example call:
    insensitiveReplaceAll("Find aBcc&def stuff ABCabc", "abc", "ab");
    

    
    
    function insensitiveReplaceAll(original, find, replace) {
      var str = "",
        remainder = original,
        lowFind = find.toLowerCase(),
        idx;
    
      while ((idx = remainder.toLowerCase().indexOf(lowFind)) !== -1) {
        str += remainder.substr(0, idx) + replace;
    
        remainder = remainder.substr(idx + find.length);
      }
    
      return str + remainder;
    }
    
    function escapeRegex(value) {
      return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
    }
    
    function updateResult() {
      var original = document.getElementById("original").value || "",
        find = document.getElementById("find").value || "",
        replace = document.getElementById("replace").value || "",
        resultEl = document.getElementById("result"),
        regexEl = document.getElementById("regex");
    
      if (original && find && replace) {
        regexEl.value = original.replace(new RegExp(escapeRegex(find), "gi"), replace);
        resultEl.value = insensitiveReplaceAll(original, find, replace);
      } else {
        regexEl.value = "";
        resultEl.value = "";
      }
    
    
    }
    
    document.addEventListener("input", updateResult);
    window.addEventListener("load", updateResult);
    
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
    
    <div class="input-group input-group-sm">
      <span class="input-group-addon">Original</span>
      <input class="form-control" id="original" value="Find aBcc&def stuff ABCabc" />
    </div>
    
    <div class="input-group input-group-sm">
      <span class="input-group-addon">Find</span>
      <input class="form-control" id="find" value="abc" />
    </div>
    
    <div class="input-group input-group-sm">
      <span class="input-group-addon">Replace</span>
      <input class="form-control" id="replace" value="ab" />
    </div>
    
    <div class="input-group input-group-sm">
      <span class="input-group-addon">Result w/o regex</span>
      <input disabled class="form-control" id="result" />
    </div>
    
    <div class="input-group input-group-sm">
      <span class="input-group-addon">Result w/ regex</span>
      <input disabled class="form-control" id="regex" />
    </div>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:1)

var s="aBc&def stuff ABCabc"
var idx = s.toUpperCase().indexOf("ABC");
while(idx!==-1){
  s = s.substr(0,idx)+"x"+s.substr(idx+2);
  idx = s.toUpperCase().indexOf("ABC");
}

答案 2 :(得分:1)

function replace(s, q, r) {
  var result = '';
  for (var i = 0; i < s.length; i++) {
    var j = 0;
    for (; j < q.length; j++) {
      if (s[i + j].toLowerCase() != q[j].toLowerCase()) break;
    }
    if (j == q.length) {
      i += q.length - 1;
      result += r;
    } else {
      result += s[i];
    }
  }
  return result;
}

该函数接受参数:

  • s - 原始字符串
  • q - 搜索查询
  • r - 替换字符串(对于每个搜索查询实例)

    1. 通过迭代每个位置来工作。

    2. 在每个位置,它会尝试检查匹配项(通过.toLowerCase()不区分大小写)。

    3. 找到的每个匹配项,都会将替换字符串插入到结果中。否则,它只是将不匹配复制到结果中。

答案 3 :(得分:1)

批准的解决方案在循环内调用toLowerCase,效率不高。

以下是改进版本:

&#13;
&#13;
Reports
&#13;
&#13;
&#13;

使用jsPerf进行测试 - https://jsperf.com/replace-case-insensitive-2/1 - 显示速度提高了37%。

答案 4 :(得分:0)

嗯,如果不考虑性能,你可能想要遍历字符串的字符以找到所需的字符串以进行替换。这样的事,也许......

for (var x = 0; x < inputString.length-3; x++) {
    if (inputString.toLowerCase.substring(x, x+2) == 'abc') {
        inputString = inputString.substring(0, x-1) + 'x' + inputString.substring(x+3);
        x = x - 2 //because your replacement is shorter you need to back up where the index is
    }
}