Заменить несколько строк на несколько других строк


213

Я пытаюсь заменить несколько слов в строке несколькими другими словами. Строка «У меня есть кошка, собака и коза».

Однако, это не производит «у меня есть собака, коза и кошка», а вместо этого производит «у меня есть кошка, кошка и кошка». Можно ли заменить несколько строк несколькими другими строками одновременно в JavaScript, чтобы получить правильный результат?

var str = "I have a cat, a dog, and a goat.";
str = str.replace(/cat/gi, "dog");
str = str.replace(/dog/gi, "goat");
str = str.replace(/goat/gi, "cat");

//this produces "I have a cat, a cat, and a cat"
//but I wanted to produce the string "I have a dog, a goat, and a cat".

Я хочу заменить несколько слов в строке несколькими другими словами, не заменяя слова, которые уже были заменены.
Андерсон Грин

У меня какой-то другой запрос, что если я не знаю, что пользователь собирается ввести кошку, собаку или козу (это происходит случайно), но всякий раз, когда появляется такое любезное слово, мне нужно заменить его, скажем, на «животное». как получить этот сценарий
Прасанна Сасне

Ответы:


445

Конкретное решение

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

var str = "I have a cat, a dog, and a goat.";
var mapObj = {
   cat:"dog",
   dog:"goat",
   goat:"cat"
};
str = str.replace(/cat|dog|goat/gi, function(matched){
  return mapObj[matched];
});

пример jsfiddle

Обобщая это

Если вы хотите динамически поддерживать регулярные выражения и просто добавлять будущие обмены на карту, вы можете сделать это

new RegExp(Object.keys(mapObj).join("|"),"gi"); 

генерировать регулярное выражение. Так что это будет выглядеть так

var mapObj = {cat:"dog",dog:"goat",goat:"cat"};

var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
str = str.replace(re, function(matched){
  return mapObj[matched];
});

И чтобы добавить или изменить другие замены, вы можете просто отредактировать карту. 

скрипка с динамическим регулярным выражением

Делая его многоразовым

Если вы хотите, чтобы это был общий шаблон, вы можете использовать это в такой функции

function replaceAll(str,mapObj){
    var re = new RegExp(Object.keys(mapObj).join("|"),"gi");

    return str.replace(re, function(matched){
        return mapObj[matched.toLowerCase()];
    });
}

Тогда вы можете просто передать str и карту замен, которые вы хотите, функции, и она вернет преобразованную строку.

возиться с функцией

Чтобы гарантировать, что Object.keys работает в старых браузерах, добавьте polyfill, например, из MDN или Es5 .


4
Я не уверен, смогу ли я использовать эту функцию для замены всех типов строк, так как символы, которые разрешены в строках JavaScript, не совпадают с символами, которые разрешены в идентификаторах JavaScript (например, ключи, которые используются здесь) ,
Андерсон Грин

2
Вы можете использовать произвольную строку в качестве свойства JavaScript. Не должно иметь значения. Вы просто не можете использовать .обозначение со всеми такими свойствами. Обозначение в скобках работает с любой строкой.
Бен Маккормик

2
Это действительно прекрасно работает. Я успешно использую это решение («конкретное») для изменения английских числовых обозначений на европейские (от 24 973,56 до 24,973,56), используя map={'.': ',', ',': '.'}и regex /\.|,/g.
Сигморал

5
Мне нравится это решение, но мне пришлось заменить return mapObj[matched.toLowerCase()];его, return mapObj[matched];поскольку я использую регистрозависимые клавиши mapObj.
Михал Моравчик

2
Вы можете избежать ключей для регулярного выражения: Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'). Вдохновлен этим ответом
robsch

9

Это может не соответствовать вашим потребностям в этом случае, но я нашел это полезным способом замены нескольких параметров в строках в качестве общего решения. Он заменит все экземпляры параметров, независимо от того, сколько раз на них ссылаются:

String.prototype.fmt = function (hash) {
        var string = this, key; for (key in hash) string = string.replace(new RegExp('\\{' + key + '\\}', 'gm'), hash[key]); return string
}

Вы бы вызвали это следующим образом:

var person = '{title} {first} {last}'.fmt({ title: 'Agent', first: 'Jack', last: 'Bauer' });
// person = 'Agent Jack Bauer'

8

Используйте пронумерованные элементы, чтобы избежать замены снова. например

let str = "I have a %1, a %2, and a %3";
let pets = ["dog","cat", "goat"];

затем

str.replace(/%(\d+)/g, (_, n) => pets[+n-1])

Как это работает: -% \ d + находит числа, следующие за%. Скобки фиксируют номер.

Это число (в виде строки) является вторым параметром лямбда-функции n.

+ N-1 преобразует строку в число, затем 1 вычитается для индексации массива домашних животных.

Число% затем заменяется строкой в ​​индексе массива.

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

В современном JavaScript: -

replace_n=(str,...ns)=>str.replace(/%(\d+)/g,(_,n)=>ns[n-1])

Интересный. Можете ли вы объяснить логику в функции замены?
Эрик Хепперле - CodeSlayer2010

5

Это сработало для меня:

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

function replaceAll(str, map){
    for(key in map){
        str = str.replaceAll(key, map[key]);
    }
    return str;
}

//testing...
var str = "bat, ball, cat";
var map = {
    'bat' : 'foo',
    'ball' : 'boo',
    'cat' : 'bar'
};
var new = replaceAll(str, map);
//result: "foo, boo, bar"


Не работает, если строка содержит символы регулярного выражения.
Ремер

О "не расширять ...": я расширил свою строку для сравнения двух строк на равенство без учета регистра. Эта функция не предоставляется String, но может случиться так, что мои приложения могут сломаться. Есть ли способ «подкласса» или «расширения» String для безопасного включения такой функции, или я должен просто определить новую функцию с двумя аргументами как часть моей библиотеки приложения?
Дэвид Спектор

4

используя Array.prototype.reduce () :

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence = 'plants are smart'

arrayOfObjects.reduce(
  (f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence
)

// as a reusable function
const replaceManyStr = (obj, sentence) => obj.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

const result = replaceManyStr(arrayOfObjects , sentence1)

пример

// /////////////    1. replacing using reduce and objects

// arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

// replaces the key in object with its value if found in the sentence
// doesn't break if words aren't found

// Example

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence1 = 'plants are smart'
const result1 = arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence1)

console.log(result1)

// result1: 
// men are dumb


// Extra: string insertion python style with an array of words and indexes

// usage

// arrayOfWords.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence)

// where arrayOfWords has words you want to insert in sentence

// Example

// replaces as many words in the sentence as are defined in the arrayOfWords
// use python type {0}, {1} etc notation

// five to replace
const sentence2 = '{0} is {1} and {2} are {3} every {5}'

// but four in array? doesn't break
const words2 = ['man','dumb','plants','smart']

// what happens ?
const result2 = words2.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence2)

console.log(result2)

// result2: 
// man is dumb and plants are smart every {5}

// replaces as many words as are defined in the array
// three to replace
const sentence3 = '{0} is {1} and {2}'

// but five in array
const words3 = ['man','dumb','plant','smart']

// what happens ? doesn't break
const result3 = words3.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence3)

console.log(result3)

// result3: 
// man is dumb and plants


Лучший ответ. Но есть ли причина использовать ${f}вместо f накопительное значение?
Дэвид Спектор

1
Если вы хотите заменить ВСЕ заданные строки, а не только первую, добавьте флаг g: "const result1 = arrayOfObjects.reduce ((f, s) => ${f}.replace (new RegExp (Object.keys (s) [ 0], 'g'), s [Object.keys (s) [0]]), предложение1) "
Дэвид Спектор

2

На тот случай, если кому-то интересно, почему оригинальное решение постера не работает:

var str = "I have a cat, a dog, and a goat.";

str = str.replace(/cat/gi, "dog");
// now str = "I have a dog, a dog, and a goat."

str = str.replace(/dog/gi, "goat");
// now str = "I have a goat, a goat, and a goat."

str = str.replace(/goat/gi, "cat");
// now str = "I have a cat, a cat, and a cat."

ха-ха ... хорошо проанализировано ... thumbsup
Deepa MG

1

пользовательская обычная функция для определения шаблона для замены и последующего использования функции замены для работы с входной строкой,

var i = new RegExp('"{','g'),
    j = new RegExp('}"','g'),
    k = data.replace(i,'{').replace(j,'}');

Если вы не знаете, пропустите, но не говорите, что это неправильный ответ. Мой случай "{" a ": 1," b ": 2}" вот так я использовал для замены вышеуказанного способа. Если это помогает другим, если они хотят для других, ответ не только для вас. @Carr
KARTHIKEYAN.A

Опять же, вы только что дали бессмысленный ответ, то, что вы делаете, тот, кто уже может ответить на вопрос, этот ответ вводит людей в заблуждение, что они могут думать по-новому, и использование RegExpобъекта может решить проблему
Carr

В этом случае у вас все еще возникает та же проблема, что и у вопроса var i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

С моим пакетом замены можно сделать следующее:

const replaceOnce = require('replace-once')

var str = 'I have a cat, a dog, and a goat.'
var find = ['cat', 'dog', 'goat']
var replace = ['dog', 'goat', 'cat']
replaceOnce(str, find, replace, 'gi')
//=> 'I have a dog, a goat, and a cat.'

Этот пакет удивительный :) Работает точно так, как я ожидал
Вишну Прасад

1
    var str = "I have a cat, a dog, and a goat.";

    str = str.replace(/goat/i, "cat");
    // now str = "I have a cat, a dog, and a cat."

    str = str.replace(/dog/i, "goat");
    // now str = "I have a cat, a goat, and a cat."

    str = str.replace(/cat/i, "dog");
    // now str = "I have a dog, a goat, and a cat."

3
ОП спросила: «Можно ли заменить несколько строк несколькими другими строками одновременно ». Это три отдельных шага.
LittleBobbyTables - Au Revoir

1

Вы можете найти и заменить строку, используя разделители.

var obj = {
  'firstname': 'John',
  'lastname': 'Doe'
}

var text = "My firstname is {firstname} and my lastname is {lastname}"

console.log(mutliStringReplace(obj,text))

function mutliStringReplace(object, string) {
      var val = string
      var entries = Object.entries(object);
      entries.forEach((para)=> {
          var find = '{' + para[0] + '}'
          var regExp = new RegExp(find,'g')
       val = val.replace(regExp, para[1])
    })
  return val;
}


0
String.prototype.replaceSome = function() {
    var replaceWith = Array.prototype.pop.apply(arguments),
        i = 0,
        r = this,
        l = arguments.length;
    for (;i<l;i++) {
        r = r.replace(arguments[i],replaceWith);
    }
    return r;
}

/ * метод replaceSome для строк принимает столько аргументов, сколько мы хотим, и заменяет все из них последним аргументом, для которого мы указали 2013 CopyRights, сохраненный для: Max Ahmed, это пример:

var string = "[hello i want to 'replace x' with eat]";
var replaced = string.replaceSome("]","[","'replace x' with","");
document.write(string + "<br>" + replaced); // returns hello i want to eat (without brackets)

* /

jsFiddle: http://jsfiddle.net/CPj89/


0
<!DOCTYPE html>
<html>
<body>



<p id="demo">Mr Blue 
has a           blue house and a blue car.</p>

<button onclick="myFunction()">Try it</button>

<script>
function myFunction() {
    var str = document.getElementById("demo").innerHTML;
    var res = str.replace(/\n| |car/gi, function myFunction(x){

if(x=='\n'){return x='<br>';}
if(x==' '){return x='&nbsp';}
if(x=='car'){return x='BMW'}
else{return x;}//must need



});

    document.getElementById("demo").innerHTML = res;
}
</script>

</body>
</html>

0

Я написал этот пакет npm stringinject https://www.npmjs.com/package/stringinject, который позволяет вам сделать следующее

var string = stringInject("this is a {0} string for {1}", ["test", "stringInject"]);

который заменит {0} и {1} элементами массива и вернет следующую строку

"this is a test string for stringInject"

или вы можете заменить заполнители на ключи объекта и значения, например:

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

"My username is tjcafferkey on Github" 

0

Для этой цели вы можете использовать https://www.npmjs.com/package/union-replacer . По сути, это string.replace(regexp, ...)аналог, который позволяет выполнять несколько замен за один проход, сохраняя при этом полную силу string.replace(...).

Раскрытие: я автор. Библиотека была разработана для поддержки более сложных настраиваемых пользователем замен, и она решает все проблемные вопросы, такие как группы захвата, обратные ссылки и замены функций обратного вызова.

Приведенные выше решения достаточно хороши для точной замены строк.


0

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

String.prototype.replaceAll=function(obj,keydata='key'){
 const keys=keydata.split('key');
 return Object.entries(obj).reduce((a,[key,val])=> a.replace(`${keys[0]}${key}${keys[1]}`,val),this)
}

const data='hids dv sdc sd ${yathin} ${ok}'
console.log(data.replaceAll({yathin:12,ok:'hi'},'${key}'))


-1

Я немного расширил @BenMcCormicks. Он работал для обычных строк, но не в том случае, если я избежал символов или групповых символов. Вот что я сделал

str = "[curl] 6: blah blah 234433 blah blah";
mapObj = {'\\[curl] *': '', '\\d: *': ''};


function replaceAll (str, mapObj) {

    var arr = Object.keys(mapObj),
        re;

    $.each(arr, function (key, value) {
        re = new RegExp(value, "g");
        str = str.replace(re, function (matched) {
            return mapObj[value];
        });
    });

    return str;

}
replaceAll(str, mapObj)

возвращает "бла-бла-234433 бла-бла"

Таким образом, он будет соответствовать ключу в mapObj, а не совпадающему слову '


// бесполезный: replaceAll («у меня есть кошка, собака и коза», {cat: «собака», собака: «коза», коза: «кошка»}) // выдает: «у меня есть кошка , кот и кот. "
девон

-3

Решение с помощью Jquery (сначала включите этот файл): замените несколько строк несколькими другими:

var replacetext = {
    "abc": "123",
    "def": "456"
    "ghi": "789"
};

$.each(replacetext, function(txtorig, txtnew) {
    $(".eng-to-urd").each(function() {
        $(this).text($(this).text().replace(txtorig, txtnew));
    });
});

Это решение требует JQuery?
Андерсон Грин

Добавлен вопросительный тег javascript, а jquery является библиотекой javascript.
Супер модель

2
@ Супер javascript tag added in question, and jquery is a libarary of javascript.Хммм, что логика отключена, она должна быть наоборот, а также просто на голову - из информации тега javascript: « Если не включен еще один тег для фреймворка / библиотеки, ожидается чистый ответ JavaScript »
Traxo

@ Андерсон Грин, да jquery необходимо для вышеупомянутого сценария.
Супер модель

@ Traxo, в большинстве веб-приложений мы используем фреймворк (начальная загрузка / материал Google). Jquery включает в себя все современные фреймворки. Итак, jquery необходим для веб-приложений.
Супер модель
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.