Ersetzen Sie mehrere Zeichenfolgen durch mehrere andere Zeichenfolgen

213

Ich versuche, mehrere Wörter in einer Zeichenfolge durch mehrere andere Wörter zu ersetzen. Die Zeichenfolge lautet "Ich habe eine Katze, einen Hund und eine Ziege."

Dies erzeugt jedoch nicht "Ich habe einen Hund, eine Ziege und eine Katze", sondern "Ich habe eine Katze, eine Katze und eine Katze". Ist es in JavaScript möglich, mehrere Zeichenfolgen gleichzeitig durch mehrere andere Zeichenfolgen zu ersetzen, damit das richtige Ergebnis erzielt wird?

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".
Anderson Green
quelle
Ich möchte mehrere Wörter in einer Zeichenfolge durch mehrere andere Wörter ersetzen, ohne bereits ersetzte Wörter zu ersetzen.
Anderson Green
Ich habe eine andere Frage, was ist, wenn ich nicht weiß, dass der Benutzer Katze, Hund oder Ziege eingeben wird (dies kommt zufällig), aber wann immer dieses Wort kommt, muss ich es durch "Tier" ersetzen. wie man dieses Szenario bekommt
Prasanna Sasne

Antworten:

445

Spezifische Lösung

Sie können eine Funktion verwenden, um jede zu ersetzen.

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 Beispiel

Verallgemeinern

Wenn Sie den regulären Ausdruck dynamisch beibehalten und der Karte nur zukünftige Austausche hinzufügen möchten, können Sie dies tun

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

um den regulären Ausdruck zu erzeugen. Dann würde es so aussehen

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];
});

Und um weitere Ersetzungen hinzuzufügen oder zu ändern, können Sie einfach die Karte bearbeiten. 

Geige mit dynamischem Regex

Wiederverwendbar machen

Wenn Sie möchten, dass dies ein allgemeines Muster ist, können Sie dies auf eine Funktion wie diese ziehen

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

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

Dann könnten Sie einfach die str und eine Zuordnung der gewünschten Ersetzungen an die Funktion übergeben und die transformierte Zeichenfolge zurückgeben.

Geige mit der Funktion

Um sicherzustellen, dass Object.keys in älteren Browsern funktioniert, fügen Sie eine Polyfüllung hinzu, z. B. aus MDN oder Es5 .

Ben McCormick
quelle
4
Ich bin mir nicht sicher, ob ich diese Funktion verwenden könnte, um alle Arten von Zeichenfolgen zu ersetzen, da die Zeichen, die in JavaScript-Zeichenfolgen zulässig sind, nicht mit den Zeichen übereinstimmen, die in JavaScript-Bezeichnern zulässig sind (z. B. die hier verwendeten Schlüssel). .
Anderson Green
2
Sie können eine beliebige Zeichenfolge als Javascript-Eigenschaft verwenden. Sollte keine Rolle spielen. Sie können die .Notation einfach nicht mit all diesen Eigenschaften verwenden. Die Notation in Klammern funktioniert mit jeder Zeichenfolge.
Ben McCormick
2
Es funktioniert in der Tat großartig. Ich verwende diese Lösung (die "spezifische") erfolgreich, um englische Notationen in europäische (24.973,56 bis 24.973.56) zu ändern, indem ich map={'.': ',', ',': '.'}und Regex verwende /\.|,/g.
Sygmoral
5
Ich liebe diese Lösung, aber ich musste sie ersetzen return mapObj[matched.toLowerCase()];, return mapObj[matched];da ich Groß- und Kleinschreibung verwende mapObj.
Michal Moravcik
2
Möglicherweise möchten Sie die Schlüssel für den regulären Ausdruck maskieren : Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'). Inspiriert von dieser Antwort
Robsch
9

Dies entspricht möglicherweise nicht genau Ihren Anforderungen in diesem Fall, aber ich habe festgestellt, dass dies als allgemeine Lösung eine nützliche Möglichkeit ist, mehrere Parameter in Zeichenfolgen zu ersetzen. Es werden alle Instanzen der Parameter ersetzt, unabhängig davon, wie oft auf sie verwiesen wird:

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

Sie würden es wie folgt aufrufen:

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

Verwenden Sie nummerierte Elemente, um ein erneutes Ersetzen zu verhindern. z.B

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

dann

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

So funktioniert es: -% \ d + findet die Zahlen, die nach einem% stehen. Die Klammern erfassen die Nummer.

Diese Zahl (als Zeichenfolge) ist der zweite Parameter n für die Lambda-Funktion.

Das + n-1 konvertiert die Zeichenfolge in die Zahl, dann wird 1 subtrahiert, um das Haustierarray zu indizieren.

Die% -Zahl wird dann durch die Zeichenfolge am Array-Index ersetzt.

Das / g bewirkt, dass die Lambda-Funktion wiederholt mit jeder Nummer aufgerufen wird, die dann durch eine Zeichenfolge aus dem Array ersetzt wird.

In modernem JavaScript: -

replace_n=(str,...ns)=>str.replace(/%(\d+)/g,(_,n)=>ns[n-1])
Quentin 2
quelle
Interessant. Können Sie die Logik in der Ersetzungsfunktion erklären?
Eric Hepperle - CodeSlayer2010
5

Das hat bei mir funktioniert:

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"
João Paulo
quelle
Funktioniert nicht, wenn die Zeichenfolge Regex-Zeichen enthält.
Roemer
Über "Nicht verlängern ...": Ich habe meinen String erweitert, um zwei Strings auf Gleichheit zu vergleichen, wobei die Groß- und Kleinschreibung nicht berücksichtigt wird. Diese Funktionalität wird nicht von String bereitgestellt, kann aber eines Tages dazu führen, dass meine Apps nicht mehr funktionieren. Gibt es eine Möglichkeit, einen String "unterzuordnen" oder zu "erweitern", um eine solche Funktion sicher einzuschließen, oder sollte ich einfach eine neue Funktion mit zwei Argumenten als Teil meiner App-Bibliothek definieren?
David Spector
4

using 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)

Beispiel

// /////////////    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

Emmanuel NK
quelle
Beste Antwort. Aber gibt es einen Grund, ${f}anstelle von f den akkumulierten Wert zu verwenden?
David Spector
1
Wenn Sie möchten, dass ALLE angegebenen Zeichenfolgen ersetzt werden, nicht nur die erste, fügen Sie das g-Flag hinzu: "const result1 = arrayOfObjects.reduce ((f, s) => ${f}.replace (new RegExp (Object.keys (s) [) 0], 'g'), s [Object.keys (s) [0]]), Satz 1) "
David Spector
2

Nur für den Fall, dass sich jemand fragt, warum die Lösung des Originalplakats nicht funktioniert:

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."
Jack
quelle
ha ha ... gut analysiert ... thumbsup
Deepa MG
1

Benutzer reguläre Funktion, um das zu ersetzende Muster zu definieren und dann die Ersetzungsfunktion zu verwenden, um an der Eingabezeichenfolge zu arbeiten.

var i = new RegExp('"{','g'),
    j = new RegExp('}"','g'),
    k = data.replace(i,'{').replace(j,'}');
KARTHIKEYAN.A
quelle
Wenn Sie nicht wissen, überspringen Sie, aber sagen Sie nicht, dass es die falsche Antwort ist. Mein Fall "{" a ": 1," b ": 2}" ist so, dass ich den obigen Weg ersetzt habe. Wenn es anderen hilft, wenn sie für andere wollen, ist die Antwort nicht nur für Sie. @ Carr
KARTHIKEYAN.A
Wieder haben Sie gerade eine bedeutungslose Antwort gegeben. Was Sie tun, ist, dass der Fragesteller bereits in der Frage tun kann. Diese Antwort wird die Leute irreführen, dass sie vielleicht neu denken und das RegExpObjekt verwenden, um das Problem zu lösen
Carr
In diesem Fall haben Sie immer noch das gleiche Problem wie die Frage des Fragestellers, wenn Sie dies tunvar i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr
1

Mit meinem einmaligen Ersatzpaket können Sie Folgendes tun:

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.'
Kodie Grantham
quelle
Dieses Paket ist unglaublich :) Funktioniert genau wie ich erwartet hatte
Vishnu Prassad
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."
Anand Kumar Singh
quelle
3
Die OP fragte : „Ist es möglich , mehrere Strings mit mehreren anderen Saiten zu ersetzen zugleich “. Dies sind drei separate Schritte.
LittleBobbyTables - Au Revoir
1

Sie können Zeichenfolgen mithilfe von Trennzeichen suchen und ersetzen.

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;
}

Naresh Kumar
quelle
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;
}

/ * replaceEinige Methode für Zeichenfolgen, für die so viele Argumente benötigt werden, wie wir möchten, und ersetzt sie alle durch das letzte Argument, das wir angegeben haben. 2013 CopyRights gespeichert für: Max Ahmed Dies ist ein Beispiel:

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/

Nazih Ahmed
quelle
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>
Jalaluddin Rumi
quelle
0

Ich habe dieses npm-Paket stringinject https://www.npmjs.com/package/stringinject geschrieben , mit dem Sie Folgendes tun können

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

Dadurch werden {0} und {1} durch die Array-Elemente ersetzt und die folgende Zeichenfolge zurückgegeben

"this is a test string for stringInject"

oder Sie können Platzhalter durch Objektschlüssel und Werte wie folgt ersetzen:

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

"My username is tjcafferkey on Github" 
tjcafferkey
quelle
0

Sie können zu diesem Zweck https://www.npmjs.com/package/union-replacer verwenden. Es handelt sich im Grunde genommen um ein string.replace(regexp, ...)Gegenstück, bei dem mehrere Ersetzungen in einem Durchgang erfolgen können, während die volle Leistung von erhalten bleibt string.replace(...).

Offenlegung: Ich bin der Autor. Die Bibliothek wurde entwickelt, um komplexere vom Benutzer konfigurierbare Ersetzungen zu unterstützen. Sie behandelt alle problematischen Dinge wie Erfassungsgruppen, Rückreferenzen und Ersetzen von Rückruffunktionen.

Die oben genannten Lösungen sind jedoch gut genug, um die Saiten exakt zu ersetzen.

Martin Čížek
quelle
-1

Ich habe @BenMcCormicks ein bisschen erweitert. Er arbeitete für normale Saiten, aber nicht, wenn ich Charakteren oder Platzhaltern entkommen war. Folgendes habe ich getan

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)

gibt "bla bla 234433 bla bla" zurück

Auf diese Weise stimmt es mit dem Schlüssel in mapObj überein und nicht mit dem übereinstimmenden Wort '

Drew Landgrave
quelle
// wertlos: replaceAll ("Ich habe eine Katze, einen Hund und eine Ziege.", {Katze: "Hund", Hund: "Ziege", Ziege: "Katze"}) // produziert: "Ich habe eine Katze , eine Katze und eine Katze. "
Devon
-3

Lösung mit Jquery (zuerst diese Datei einschließen): Ersetzen Sie mehrere Zeichenfolgen durch mehrere andere Zeichenfolgen:

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));
    });
});
Supermodel
quelle
Benötigt diese Lösung JQuery?
Anderson Green
Javascript-Tag in Frage hinzugefügt, und JQuery ist eine Bibliothek von Javascript.
Supermodel
2
@Super javascript tag added in question, and jquery is a libarary of javascript.Hmmm, diese Logik ist ausgeschaltet, es sollte umgekehrt sein und auch nur ein Kopf hoch - von Javascript-Tag-Informationen: " Sofern kein anderes Tag für ein Framework / eine Bibliothek enthalten ist, wird eine reine JavaScript-Antwort erwartet. "
Traxo
@Anderson Green, ja, für das obige Skript wird eine Abfrage benötigt.
Super Model
@ Traxo, in den meisten Webanwendungen verwenden wir Framework (Bootstrap / Google-Material). Jquery ist in allen modernen Frameworks enthalten. Daher ist jquery ein notwendiges Element für Webanwendungen.
Super Model