2013-06-23 3 views
14

У меня есть набор строк, которые мне нужно заменить, но мне нужно сохранить регистр букв. как входные слова, так и выходные слова имеют одинаковую длину.Заменить текст, но сохранить регистр

Например, если мне нужно заменить "ABCD" с "QWER", то следующее должно произойти:

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

и так далее.

Сейчас я использую JavaScript replace, но заглавные буквы теряются при переводе.

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

Любая помощь будет принята с благодарностью.

+0

Целевая строка и замена известны или они будут динамическими? – pvnarula

+0

Извините, я не понимаю ваш вопрос. Но это так: я переписываю текст, введенный пользователем. У меня есть список правил, например, «ca» транскрибируется на «kb», но мне нужно сохранить заглавные буквы, поэтому «cA» транскрибируется на «kB». –

+1

Я бы сделал это за 2 шага, сначала «oooAsdFoooo» .search (r), который возвращает индекс, а затем обрабатывает регистр. Но я был бы взволнован, если есть только с регулярным выражением – bert

ответ

5

Вот помощник:

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); 
}); 
+1

Это хорошо, но работает только для ASCII. :) – Tomalak

+2

@Tomalak: При необходимости измените 'p> = 65 && p <65 + 26' на' UPPERCASE.test (p) ', измените charCodeAt' на charAt' и определите' var UPPERCASE =/[anyletters ] /; '. – Ryan

+0

Или, может быть, 'toLocale {верхний, нижний} случай'. – Ryan

1
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" 
+1

Это заменяет отдельные символы, хотя в оригинальном вопросе речь идет о замене подстрок.В вашем exmaple строка ввода не содержит «abcdefg», поэтому ничего не нужно заменять. – jcsanyi

+0

@jcsanyi Hm. Я так не понял. Но, вероятно, вы правы. – Tomalak

1

Вы можете создать свою собственную функцию замены, такие как

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, показывающий пример (обратите внимание, что объект имеет все строчные буквы, но сама функция также смотрит на случай строки)

0

Развернувшись на ответ Райана О'Хары, нижеприведенное решение избегает использования 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); 
} 
1

Это должно заменить при сохранении корпуса. Пожалуйста, дайте мне знать, найдут ли кто-либо недостатки в этом решении. Надеюсь, это поможет. Спасибо!

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");