【问题标题】:Replace text but keep case替换文本但保留大小写
【发布时间】:2022-01-16 15:06:17
【问题描述】:

我有一组字符串需要替换,但我需要保留字母的大小写。

输入字和输出字的长度相同。

例如,如果我需要将“abcd”替换为“qwer”,那么应该会发生以下情况:

"AbcD" translates to "QweR"
"abCd" translates to "qwEr"

等等。

现在我正在使用 JavaScript 的 replace,但翻译时会丢失大写字母。

r = new RegExp( "(" + 'asdf' + ")" , 'gi' );
"oooAsdFoooo".replace(r, "qwer");

任何帮助将不胜感激。

【问题讨论】:

  • 目标字符串和替换是已知的,否则它们将是动态的?
  • 对不起,我不明白你的问题。但情况就是这样:我正在转录用户输入的文本。我有一个规则列表,比如“ca”转写为“kb”,但我需要保留大写字母,所以“cA”转写为“kB”。
  • 我会分两步完成,首先是 "oooAsdFoooo".search(r) 返回索引,然后处理案例。但如果有办法只使用正则表达式,我会很兴奋
  • 您有特定字母到字母映射的列表吗?例如 a==q, A== Q 。所以如果 a 是输入,它总是 q(大写或小写)
  • 我在这里找到了一个更简单、更优雅的解决方案来解决似乎相同的问题:stackoverflow.com/questions/28841045/…

标签: javascript


【解决方案1】:

这是一个助手:

function matchCase(text, pattern) {
    var result = '';

    for(var i = 0; i < text.length; i++) {
        var c = text.charAt(i);
        var p = pattern.charCodeAt(i);

        if(p >= 65 && p < 65 + 26) {
            result += c.toUpperCase();
        } else {
            result += c.toLowerCase();
        }
    }

    return result;
}

那么你可以:

"oooAsdFoooo".replace(r, function(match) {
    return matchCase("qwer", match);
});

【讨论】:

  • 这很好,但仅适用于 ASCII。 :)
  • @Tomalak:如有必要,将p &gt;= 65 &amp;&amp; p &lt; 65 + 26更改为UPPERCASE.test(p),将charCodeAt更改为charAt,并定义var UPPERCASE = /[whateverletters]/;
  • 或者toLocale{Upper,Lower}Case
【解决方案2】:
String.prototype.translateCaseSensitive = function (fromAlphabet, toAlphabet) {
    var fromAlphabet = fromAlphabet.toLowerCase(),
        toAlphabet = toAlphabet.toLowerCase(),
        re = new RegExp("[" + fromAlphabet + "]", "gi");

    return this.replace(re, function (char) {
        var charLower = char.toLowerCase(),
            idx = fromAlphabet.indexOf(charLower);

        if (idx > -1) {
            if (char === charLower) {
                return toAlphabet[idx];
            } else {
                return toAlphabet[idx].toUpperCase();
            }
        } else {
            return char;
        }
    });
};

"AbcD".translateCaseSensitive("abcdefg", "qwertyu")

将返回:

"QweR"

【讨论】:

  • 这会替换单个字符 - 原始问题是关于替换子字符串。在您的示例中,输入字符串不包含“abcdefg”,因此不应替换任何内容。
  • @jcsanyi 嗯。我不是这么理解的。但很可能你是对的。
【解决方案3】:

您可以创建自己的替换功能,例如

 if(!String.prototype.myreplace){
String.prototype.myreplace = (function(obj){
    return this.replace(/[a-z]{1,1}/gi,function(a,b){
       var r = obj[a.toLowerCase()] || a;
        return a.charCodeAt(0) > 96? r.toLowerCase() : r.toUpperCase();
    });
});
}

这需要一个映射不同字母的对象。可以这样调用

  var obj = {a:'q',b:'t',c:'w'};

  var s = 'AbCdea';
  var n = s.myreplace(obj);
  console.log(n);

这意味着如果需要,您可以使用不同的映射传递不同的对象。这是一个简单的fiddle 显示示例(注意对象都是小写,但函数本身也会查看字符串的大小写)

【讨论】:

【解决方案4】:

扩展 Ryan O'Hara 的回答,以下解决方案避免使用 charCodes 以及在使用它们时可能遇到的问题。当字符串长度不同时,它还可以确保替换完成。

function enforceLength(text, pattern, result) {
  if (text.length > result.length) {  
    result = result.concat(text.substring(result.length, text.length));
  }

  if (pattern.length > text.length) {
    result = result.substring(0, text.length);
  }

  return result;
}

function matchCase(text, pattern){
  var result = '';

  for (var i =0; i < pattern.length; i++){
    var c = text.charAt(i);
    var p = pattern.charAt(i);

    if(p === p.toUpperCase()) {
       result += c.toUpperCase();
    } else {
       result += c.toLowerCase();
    }
  }  
  return enforceLength(text, pattern, result);
}

【讨论】:

    【解决方案5】:

    这应该在保留大小写的同时替换。如果有人在此解决方案中发现任何缺陷,请告诉我。我希望这有帮助。谢谢!

    function myReplace(str, before, after) {
    
          var match=function(before,after){
            after=after.split('');
            for(var i=0;i<before.length;i++)
              {
    
                if(before.charAt(i)==before[i].toUpperCase())
                  {
                    after[i]=after[i].toUpperCase();
                  }
                else  if(before.charAt(i)==before[i].toLowerCase())
                  {
                    after[i]=after[i].toLowerCase();
                  }
                return after.join('');
              }
    
          };
               console.log(before,match(before,after));
              str =str.replace(before,match(before,after)); 
    
    
          return str;
        }
    
        myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");
    

    【讨论】:

      【解决方案6】:

      这是一个replaceCase 函数:

      1. 我们将输入模式转换为正则表达式
      2. 我们有一个嵌套的替换函数,它遍历每个字符
      3. 我们使用正则表达式/[A-Z]/来识别大写字母,否则我们假设一切都是小写的

      function replaceCase(str, pattern, newStr) {
        const rx = new RegExp(pattern, "ig")
        const replacer = (c, i) => c.match(/[A-Z]/) ? newStr[i].toUpperCase() : newStr[i]
        return str.replace(rx, (oldStr) => oldStr.replace(/./g, replacer) )
      }
      
      let out = replaceCase("This is my test string: AbcD", "abcd", "qwer")
      console.log(out) // This is my test string: QweR
      out = replaceCase("This is my test string: abCd", "abcd", "qwer")
      console.log(out) // This is my test string: qwEr

      【讨论】:

      • 能否请您用标准的 jQuery 或 vanilla JavaScript 编写这个函数? EMCA 2015 不兼容我们支持的所有浏览器。
      【解决方案7】:

      我有一个句子,我必须用另一个单词替换每个单词,并且该单词可以比它替换的单词更长/更短,因此它与问题相似,但它们不是固定长度,而是动态的。

      我的解决方案

      为简单起见,我只关注一个词。

      const oldWord = "tEsT";
      const newWord = "testing";
      

      拆分两个单词,以便我可以遍历每个单独的字母。

      const oldWordLetters = oldWord.split("");
      const newWordLetters = newWord.split("");
      

      现在,我将遍历newWord 字母并使用它的索引然后在相同位置获得对应的oldWord 字母。然后我会检查旧字母是否大写,如果是,则将新字母也放在相同的位置。

      for (const [i, letter] of newWordLetters.entries()) {
        const oldLetter = oldWordLetters[i];
      
        // stop iterating if oldWord is shorter (not enough letters to copy case).
        if (!oldLetter) {
          break;
        }
      
        const isCapital = oldLetter === oldLetter.toUpperCase();
      
        // make the new letter in the same position as the old letter capital
        if (isCapital) {
          newWordLetters[i] = letter.toUpperCase();
        }
      }
      

      再次加入字母后,最终的世界将是tEsTing

      const finalWord = newWordLetters.join("");
      
      console.log(finalWord); // "tEsTing"
      

      完整代码

      const oldWord = "tEsT";
      const newWord = "testing";
      
      const oldWordLetters = oldWord.split("");
      const newWordLetters = newWord.split("");
      
      for (const [i, letter] of newWordLetters.entries()) {
        const oldLetter = oldWordLetters[i];
      
        // stop iterating if oldWord is shorter (not enough letters to copy case).
        if (!oldLetter) {
          break;
        }
      
        const isCapital = oldLetter === oldLetter.toUpperCase();
      
        // make the new letter in the same position as the old letter capital
        if (isCapital) {
          newWordLetters[i] = letter.toUpperCase();
        }
      }
      
      const finalWord = newWordLetters.join("");
      
      console.log(finalWord);

      【讨论】:

        【解决方案8】:

        我将把它留在这里以供参考。

        场景:项目列表中不区分大小写的搜索框,字符串的部分匹配应突出显示但保持原始大小写。

        highlight() {
          const re = new RegExp(this.searchValue, 'gi'); // global, insensitive
          const newText = name.replace(re, `<b>$&</b>`);
          return newText;
        }
        

        $& 是与大小写匹配的文本

        【讨论】:

          【解决方案9】:

          我认为这可行

          function formatItem(text, searchText){
              const search = new RegExp(escapeRegExp(searchText), 'iu')
              return text?.toString().replace(search, (m) => `<b>${m}</b>`)
          }
          
          function escapeRegExp(text) {
            return text?.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') ?? '';
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-10-21
            • 1970-01-01
            • 2011-06-26
            • 1970-01-01
            • 1970-01-01
            • 2010-09-26
            • 1970-01-01
            • 2012-09-29
            相关资源
            最近更新 更多