根據一條線:

s = "Test abc test test abc test test test abc test test abc";

这似乎只是在上面的行中删除ABC的第一次出现:

s = s.replace('abc', '');

如何替代所有事件?


当前回答

就像上面的分裂/合并解决方案一样,下面的解决方案与逃避字符没有任何问题,与常规表达方法不同。

function replaceAll(s, find, repl, caseOff, byChar) {
    if (arguments.length<2)
        return false;
    var destDel = ! repl;       // If destDel delete all keys from target
    var isString = !! byChar;   // If byChar, replace set of characters
    if (typeof find !== typeof repl && ! destDel)
        return false;
    if (isString && (typeof find !== "string"))
        return false;

    if (! isString && (typeof find === "string")) {
        return s.split(find).join(destDel ? "" : repl);
    }

    if ((! isString) && (! Array.isArray(find) ||
        (! Array.isArray(repl) && ! destDel)))
        return false;

    // If destOne replace all strings/characters by just one element
    var destOne = destDel ? false : (repl.length === 1);

    // Generally source and destination should have the same size
    if (! destOne && ! destDel && find.length !== repl.length)
        return false

    var prox, sUp, findUp, i, done;
    if (caseOff)  { // Case insensitive

    // Working with uppercase keys and target
    sUp = s.toUpperCase();
    if (isString)
       findUp = find.toUpperCase()
    else
       findUp = find.map(function(el) {
                    return el.toUpperCase();
                });
    }
    else { // Case sensitive
        sUp = s;
        findUp = find.slice(); // Clone array/string
    }

    done = new Array(find.length); // Size: number of keys
    done.fill(null);

    var pos = 0;  // Initial position in target s
    var r = "";   // Initial result
    var aux, winner;
    while (pos < s.length) {       // Scanning the target
        prox  = Number.MAX_SAFE_INTEGER;
        winner = -1;  // No winner at the start
        for (i=0; i<findUp.length; i++) // Find next occurence for each string
            if (done[i]!==-1) { // Key still alive

                // Never search for the word/char or is over?
                if (done[i] === null || done[i] < pos) {
                    aux = sUp.indexOf(findUp[i], pos);
                    done[i] = aux;  // Save the next occurrence
                }
                else
                    aux = done[i]   // Restore the position of last search

                if (aux < prox && aux !== -1) { // If next occurrence is minimum
                    winner = i; // Save it
                    prox = aux;
                }
        } // Not done

        if (winner === -1) { // No matches forward
            r += s.slice(pos);
            break;
        } // No winner

        // Found the character or string key in the target

        i = winner;  // Restore the winner
        r += s.slice(pos, prox); // Update piece before the match

        // Append the replacement in target
        if (! destDel)
            r += repl[destOne ? 0 : i];
        pos = prox + (isString ? 1 : findUp[i].length); // Go after match
    }  // Loop

    return r; // Return the resulting string
}

文档如下:

替代All Syntax ====== 替代All(s, find, [repl, caseOff, byChar) 参数 ==========“s” 是替代序列的目标. “find” 可以是序列或序列的序列. “repl” 应该是相同的类型“find” 或空的 如果“find” 是序列,它是一个简单的替代所有“find” 事件在“s” 由序列“repl” 如果“find” 是序列,它将取代

function l() {
    return console.log.apply(null, arguments);
}

var k = 0;
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"], ["do", "fa"]));  // 1
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"], ["do"])); // 2
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"])); // 3
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
     "aeiou", "", "", true)); // 4
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      "aeiou", "a", "", true)); // 5
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      "aeiou", "uoiea", "", true)); // 6
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      "aeiou", "uoi", "", true)); // 7
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"], ["do", "fa", "leg"])); // 8
l(++k, replaceAll("BANANA IS A RIPE FRUIT HARVESTED NEAR THE RIVER",
      ["ri", "nea"], ["do", "fa"])); // 9
l(++k, replaceAll("BANANA IS A RIPE FRUIT HARVESTED NEAR THE RIVER",
      ["ri", "nea"], ["do", "fa"], true)); // 10
return;

其他回答

我在“图书馆”部分中添加了下面的功能到这个性能测试页面:

首頁 〉外文書 〉文學 〉文學 〉WEB

function _replace(t, s, r){
    var i = t.indexOf(s);
    if (i == -1) return t;
    return t.slice(0, i) + r + _replace(t.slice(i + s.length, t.length), s,r);
}

把它当作测试:

var replaced = _replace(testString, 'abc', '123');

想法的一部分是,如果链条不太大,它可能会在CPU存储库中结束;通过它并粘贴它的碎片将这些比特放入存储库中,然后搜索可以完全使用CPU存储数据运行。

这不是尽可能快的,但它是尽可能快的,我可以管理没有可转换的线条. 在JavaScript中的线条可能有一个指标每个元素,因此,一个解决方案涉及很多线条元素是不可能像CPU缓存友好。

最好的解决方案,以取代我们使用的任何字符的 indexOf(),包括(),和substring()功能,以取代相匹配的行与提供的行在当前行。

String.indexOf() 函数是找到 nth 匹配指数位置. String.includes() 方法确定一个行是否可以在另一个行中找到,随时返回真实或虚假。

下面的功能允许使用任何字符. 如 RegExp 不允许某些特殊字符如 ** 和某些字符需要逃避,如 $。

String.prototype.replaceAllMatches = function(obj) { // Obj format: { 'matchkey' : 'replaceStr' }
    var retStr = this;
    for (var x in obj) {
        //var matchArray = retStr.match(new RegExp(x, 'ig'));
        //for (var i = 0; i < matchArray.length; i++) {
        var prevIndex = retStr.indexOf(x); // matchkey = '*', replaceStr = '$*' While loop never ends.
        while (retStr.includes(x)) {
            retStr = retStr.replaceMatch(x, obj[x], 0);
            var replaceIndex = retStr.indexOf(x);
            if( replaceIndex <  prevIndex + (obj[x]).length) {
                break;
            } else {
                prevIndex = replaceIndex;
            }
        }
    }
    return retStr;
};
String.prototype.replaceMatch = function(matchkey, replaceStr, matchIndex) {
    var retStr = this, repeatedIndex = 0;
    //var matchArray = retStr.match(new RegExp(matchkey, 'ig'));
    //for (var x = 0; x < matchArray.length; x++) {
    for (var x = 0; (matchkey != null) && (retStr.indexOf(matchkey) > -1); x++) {
        if (repeatedIndex == 0 && x == 0) {
            repeatedIndex = retStr.indexOf(matchkey);
        } else { // matchIndex > 0
            repeatedIndex = retStr.indexOf(matchkey, repeatedIndex + 1);
        }
        if (x == matchIndex) {
            retStr = retStr.substring(0, repeatedIndex) + replaceStr + retStr.substring(repeatedIndex + (matchkey.length));
            matchkey = null; // To break the loop.
        }
    }
    return retStr;
};

我们还可以使用常规表达式对象,以匹配文本与模式,以下是将常规表达式对象使用的功能。

String.prototype.replaceAllRegexMatches = function(obj) { // Obj format: { 'matchkey' : 'replaceStr' }
    var retStr = this;
    for (var x in obj) {
        retStr = retStr.replace(new RegExp(x, 'ig'), obj[x]);
    }
    return retStr;
};

请注意,常规表达式是没有引用的。


var str = "yash yas $dfdas.**";
console.log('String: ', str);

// No need to escape any special character
console.log('Index matched replace: ', str.replaceMatch('as', '*', 2));
console.log('Index Matched replace: ', str.replaceMatch('y', '~', 1));
console.log('All Matched replace: ', str.replaceAllMatches({'as': '**', 'y':'Y', '$':'-'}));
console.log('All Matched replace : ', str.replaceAllMatches({'**': '~~', '$':'&$&', '&':'%', '~':'>'}));

// You need to escape some special Characters
console.log('REGEX all matched replace: ', str.replaceAllRegexMatches({'as' : '**', 'y':'Y', '\\$':'-'}));

结果:

String:  yash yas $dfdas.**
Index Matched replace:  yash yas $dfd*.**
Index Matched replace:  yash ~as $dfdas.**

All Matched replace:  Y**h Y** -dfd**.**
All Matched replace:  yash yas %$%dfdas.>>

REGEX All Matched replace:  Y**h Y** -dfd**.**

我已经阅读了这个问题和答案,但我找不到一个合适的解决方案,虽然答案是相当有用的,我决定创建自己的解决方案从切割。

例如,对于搜索结果,我需要用相同的案例取代它,如果我处理内部HTML,我可以轻松地损害HTML标签(例如,在href属性中出现 hr)。

因此,我写的功能,以突出搜索结果在一个表,在那里表数据细胞可能有链接在内部,以及其他HTML标签。

我決定為所有人提供相同的問題的解決方案. 當然,你可以用它不僅為表,但為任何元素。

/* Iterate over table data cells to insert a highlight tag */
function highlightSearchResults(textFilter) {
  textFilter = textFilter.toLowerCase().replace('<', '&lt;').replace('>', '&gt;');
  let tds;
  tb = document.getElementById('sometable'); //root element where to search
  if (tb) {
    tds = tb.getElementsByTagName("td"); //sub-elements where to make replacements
  }
  if (textFilter && tds) {
    for (td of tds) {
      //specify your span class or whatever you need before and after
      td.innerHTML = insertCaseInsensitive(td.innerHTML, textFilter, '<span class="highlight">', '</span>');
    }
  }
}

/* Insert a highlight tag */
function insertCaseInsensitive(srcStr, lowerCaseFilter, before, after) {
  let lowStr = srcStr.toLowerCase();
  let flen = lowerCaseFilter.length;
  let i = -1;
  while ((i = lowStr.indexOf(lowerCaseFilter, i + 1)) != -1) {
    if (insideTag(i, srcStr)) continue;
    srcStr = srcStr.slice(0, i) + before + srcStr.slice(i, i+flen) + after + srcStr.slice(i+flen);
    lowStr = srcStr.toLowerCase();
    i += before.length + after.length;
  }
  return srcStr;
}

/* Check if an ocurrence is inside any tag by index */
function insideTag(si, s) {
  let ahead = false;
  let back = false;
  for (let i = si; i < s.length; i++) {
    if (s[i] == "<") {
      break;
    }
    if (s[i] == ">") {
      ahead = true;
      break;
    }
  }
  for (let i = si; i >= 0; i--) {
    if (s[i] == ">") {
      break;
    }
    if (s[i] == "<") {
      back = true;
      break;
    }
  }
  return (ahead && back);
}
str = "Test abc test test abc test test test abc test test abc"

str.split(' ').join().replace(/abc/g,'').replace(/,/g, ' ')

如果你试图确保你正在寻找的链条不会存在,即使在更换后,你需要使用一个旋转。

例如:

var str = 'test aabcbc';
str = str.replace(/abc/g, '');

完成后,你将仍然有“测试ABC”!

最简单的路径来解决这个问题是:

var str = 'test aabcbc';
while (str != str.replace(/abc/g, '')){
   str.replace(/abc/g, '');
}

也许(在投票的危险下)可以结合为一个稍微更有效但更少可读的形式:

var str = 'test aabcbc';
while (str != (str = str.replace(/abc/g, ''))){}
// alert(str); alerts 'test '!

例如,如果我们有“a、b”并希望删除所有复制曲线。 [在这种情况下,可以进行.replace(/+、/g、'),但在某个时候, regex 会变得复杂和缓慢,而不是旋转。