Замените сразу несколько строк


есть ли простой эквивалент этого в JavaScript?

$find = array("<", ">", "n");
$replace = array("&lt;", "&gt;", "<br/>");

$textarea = str_replace($find, $replace, $textarea); 

это использование PHP str_replace, что позволяет использовать массив слов для поиска и замены. Могу ли я сделать что-то подобное с помощью JavaScript / jQuery?

...
var textarea = $(this).val();

// string replace here

$("#output").html(textarea);
...
13 56

13 ответов:

вы можете расширить объект String с помощью своей собственной функции, которая делает то, что вам нужно (полезно, если когда-либо отсутствовала функциональность):

String.prototype.replaceArray = function(find, replace) {
  var replaceString = this;
  for (var i = 0; i < find.length; i++) {
    replaceString = replaceString.replace(find[i], replace[i]);
  }
  return replaceString;
};

для глобальной замены вы можете использовать регулярное выражение:

String.prototype.replaceArray = function(find, replace) {
  var replaceString = this;
  var regex; 
  for (var i = 0; i < find.length; i++) {
    regex = new RegExp(find[i], "g");
    replaceString = replaceString.replace(regex, replace[i]);
  }
  return replaceString;
};

чтобы использовать функцию, она будет похожа на ваш пример PHP:

var textarea = $(this).val();
var find = ["<", ">", "\n"];
var replace = ["&lt;", "&gt;", "<br/>"];
textarea = textarea.replaceArray(find, replace);

Распространенная Ошибка

почти все ответы на этой странице используют кумулятивную замену и, таким образом, страдают тем же недостатком, когда строки замены сами подлежат замене. Вот несколько примеров, когда этот шаблон терпит неудачу (h / t @KurokiKaze @derekdreery):

function replaceCumulative(str, find, replace) {
  for (var i = 0; i < find.length; i++)
    str = str.replace(new RegExp(find[i],"g"), replace[i]);
  return str;
};

// Fails in some cases:
console.log( replaceCumulative( "tar pit", ['tar','pit'], ['capitol','house'] ) );
console.log( replaceCumulative( "you & me", ['you','me'], ['me','you'] ) );

решение

function replaceBulk( str, findArray, replaceArray ){
  var i, regex = [], map = {}; 
  for( i=0; i<findArray.length; i++ ){ 
    regex.push( findArray[i].replace(/([-[\]{}()*+?.\^$|#,])/g,'\') );
    map[findArray[i]] = replaceArray[i]; 
  }
  regex = regex.join('|');
  str = str.replace( new RegExp( regex, 'g' ), function(matched){
    return map[matched];
  });
  return str;
}

// Test:
console.log( replaceBulk( "tar pit", ['tar','pit'], ['capitol','house'] ) );
console.log( replaceBulk( "you & me", ['you','me'], ['me','you'] ) );

Примечание:

это более совместимый вариант @elchininet решение, который использует map() и Array.indexOf() и, таким образом, не будет работать в IE8 и старше.

реализация@elchininet вернее для PHP str_replace(), потому что он также позволяет строки в качестве параметров поиска/замены, и будет использовать первый найти совпадение массива, если есть дубликаты (моя версия будет использовать последний). Я не принимал строки в этой реализации, потому что этот случай уже обрабатывается встроенным JS String.replace().

text = text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br/>');

вы можете использовать метод замены String объект с функцией во втором параметре:

Первый метод (с помощью найти и заменить объект)

var findreplace = {"<" : "&lt;", ">" : "&gt;", "\n" : "<br/>"};

textarea = textarea.replace(new RegExp("(" + Object.keys(findreplace).map(function(i){return i.replace(/[.?*+^$[\]\(){}|-]/g, "\$&")}).join("|") + ")", "g"), function(s){ return findreplace[s]});

jsfiddle

Второй метод (используя два массива, найти и заменить)

var find = ["<", ">", "\n"];
var replace = ["&lt;", "&gt;", "<br/>"];

textarea = textarea.replace(new RegExp("(" + find.map(function(i){return i.replace(/[.?*+^$[\]\(){}|-]/g, "\$&")}).join("|") + ")", "g"), function(s){ return replace[find.indexOf(s)]});

jsfiddle

нужные функция:

function str_replace($f, $r, $s){
   return $s.replace(new RegExp("(" + $f.map(function(i){return i.replace(/[.?*+^$[\]\(){}|-]/g, "\$&")}).join("|") + ")", "g"), function(s){ return $r[$f.indexOf(s)]});
}

$textarea = str_replace($find, $replace, $textarea);

EDIT

этой function признает String или Array параметры:

function str_replace($f, $r, $s){
    return $s.replace(new RegExp("(" + (typeof($f) == "string" ? $f.replace(/[.?*+^$[\]\(){}|-]/g, "\$&") : $f.map(function(i){return i.replace(/[.?*+^$[\]\(){}|-]/g, "\$&")}).join("|")) + ")", "g"), typeof($r) == "string" ? $r : typeof($f) == "string" ? $r[0] : function(i){ return $r[$f.indexOf(i)]});
}

более визуальный подход:

String.prototype.htmlProtect = function() {
  var replace_map;

  replace_map = {
    '\n': '<br />',
    '<': '&lt;',
    '>': '&gt;'
  };

  return this.replace(/[<>\n]/g, function(match) { // be sure to add every char in the pattern
    return replace_map[match];
  });
};

и вот как вы это называете:

var myString = "<b>tell me a story, \n<i>bro'</i>";
var myNewString = myString.htmlProtect();

// &lt;b&gt;tell me a story, <br />&lt;i&gt;bro'&lt;/i&gt;

вы можете заглянуть в библиотеку JS под названием phpJS.

Это позволяет использовать функцию str_replace аналогично тому, как вы бы использовали ее в PHP. Есть также много других функций php, "портированных" на JavaScript.

http://phpjs.org/functions/str_replace:527

нет способа сделать это в одном вызове метода, вам придется либо связывать вызовы вместе, либо писать функцию, которая вручную делает то, что вам нужно.

var s = "<>\n";
s = s.replace("<", "&lt;");
s = s.replace(">", "&gt;");
s = s.replace("\n", "<br/>");

для тегов, вы должны быть в состоянии просто установить содержание с .text() вместо .html().

пример: http://jsfiddle.net/Phf4u/1/

var textarea = $('textarea').val().replace(/<br\s?\/?>/, '\n');

$("#output").text(textarea);

...или если вы просто хотели убрать <br> элементы, вы могли бы избавиться от .replace(), и временно сделать их элементами DOM.

пример: http://jsfiddle.net/Phf4u/2/

var textarea = $('textarea').val();

textarea = $('<div>').html(textarea).find('br').remove().end().html();

$("#output").text(textarea);
String.prototype.replaceArray = function (find, replace) {
    var replaceString = this;
    for (var i = 0; i < find.length; i++) {
        // global replacement
        var pos = replaceString.indexOf(find[i]);
        while (pos > -1) {
            replaceString = replaceString.replace(find[i], replace[i]);
            pos = replaceString.indexOf(find[i]);
        }
    }
    return replaceString;
};

var textT = "Hello world,,,,, hello people.....";
var find = [".",","];
var replace = ['2', '5'];
textT = textT.replaceArray(find, replace);
// result: Hello world55555 hello people22222

вот простой подход на основе карт. Замена струн на 95% быстрее, чем замена регулярных выражений.

function strReplaceMap(str, map) {
  for (var search in map) {
    str = str.replace(search, map[search]);
  }
  return str;
}

и вот эталон сравнивая это выражение.

один из методов:

var text = $(this).val();
text = text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
$("#output").html(text);

у меня был случай, когда я должен был удалить символы из строки и сделал это так:

 let badChars = ['å', 'ä', 'ö'];
 let newName = fileName.split("").filter((chr) => badChars.indexOf(chr) === -1).join("");

было бы очень аккуратно, если бы строки были по своей сути символьными массивами в javascript, так что нам не нужны были бы эти split/join, например newName = fileName.filter((chr) => badChars.indexOf(chr) === -1) но я все еще думаю, что это аккуратно и читабельно, если вам нужно иметь дело только с символами, а не с susbstrings.

верхний ответ эквивалентен выполнению:

let text = find.reduce((acc, item, i) => {
  const regex = new RegExp(item, "g");
  return acc.replace(regex, replace[i]);
}, textarea);

при этом:

var textarea = $(this).val();
var find = ["<", ">", "\n"];
var replace = ["&lt;", "&gt;", "<br/>"];

в этом случае никакого императивного программирования не происходит.