4 Stimmen

String.Replace ersetzt nicht alle Übereinstimmungen.

Warum ersetzt line2 nur abwechselnd die Hälfte der Vorkommen?

    Dim line1 As String = "AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF"
    Dim line2 As String = "AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF"
    Dim line3 As String = "AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF"

    line1 = line1.Replace("CCC", "")
    line2 = line2.Replace("|CCC|", "||")
    line3 = line3.Replace("CCC|", "|")

Ergebnis:

line1 = "AAA|BBB|||||EEE|FFF" -- OK, aber scheitert, wenn das Element "..|ZZZCCCZZZ|.." ist
line2 = "AAA|BBB||CCC||CCC|EEE|FFF" -- Nicht OK
line3 = "AAA|BBB|||||EEE|FFF" -- OK, scheitert jedoch bei ähnlichen Fällen wie Line1 beim Randfall "..|ZZZCCC|.."

Ich habe versucht, RegEx zu verwenden, aber erhalte ähnliche Ergebnisse.

Gibt es wirklich keinen besseren Weg als diesen unten?

Do While line1.Contains("|CCC|")
    line1 = line1.Replace("|CCC|", "||")
Loop

9voto

Chris Sinclair Punkte 22660

Sobald es das erste Token findet, beginnt es nach dem nächsten Token nach diesem Token zu suchen. Es findet also |CCC|, ersetzt es, dann fährt es fort und das erste, was es sieht, ist CCC|, was nicht übereinstimmt. Es scannt nicht vorab den String nach Tokens, die ersetzt werden sollen.

Man könnte es sich so vorstellen:

Gegeben ist AAA|BBB|CCC|CCC|CCC|CCC|EEE|FFF

Es läuft bis zu AAA|BBB|CCC| HALT |CCC| wurde gefunden, lassen Sie uns unsere Zeichenkette aufbauen:

AAA|BBB + || (unsere Ersetzung)

Lassen Sie uns nun fortfahren, wir haben nun CCC|CCC|CCC|EEE|FFF übrig, mit dem wir arbeiten können.

Es läuft bis zu CCC|CCC| HALT |CCC| wurde gefunden, lassen Sie uns fortfahren und zu unserer Zeichenkette hinzufügen:

AAA|BBB||CCC + || (unsere Ersetzung)

Lassen Sie uns nun fortfahren, wir haben nun CCC|CCC|EEE|FFF und so weiter.

EDIT: In Anbetracht des Eintrags auf MSDN der den Rückgabewert beschreibt:

Ein String, der dem aktuellen String entspricht, außer dass alle Vorkommen von oldValue durch newValue ersetzt wurden.

Man könnte das so verstehen, dass es den String vorab scannt und alle Übereinstimmungen findet. Ich sehe nichts in der MSDN-Dokumentation, die diesen Sonderfall beschreibt. Vielleicht sollte das der MSDN-Dokumentation hinzugefügt werden.

3voto

juharr Punkte 31014

Statt regulärer Ausdrücke oder string.Replace könnten Sie die Werte parsen, diejenigen filtern, die Sie nicht möchten, und sie anschließend wieder zusammenfügen.

line1 = string.Join("|", line1.Split("|").Select(s => s == "CCC" ? "" : s).ToArray());

Entschuldigung, ich kenne nicht das Äquivalent in VB.

1voto

Leon Punkte 3193

Für jeden in der Zukunft habe ich eine Erweiterungsmethode hinzugefügt, um diese Einschränkung im Framework zu überwinden:

Public Function ReplaceAll(ByVal original As String, ByVal oldValue As String, ByVal newValue As String) As String

    If newValue.Contains(oldValue) Then
        Throw New ArgumentException("Neuer Wert kann kein Teilwert von OldValue sein, da unendliche Ersetzungen auftreten können.", newValue)
    End If

    Dim maxIterations As Integer = original.Length \ oldValue.Length

    While maxIterations > 0 AndAlso original.Contains(oldValue)
        original = original.Replace(oldValue, newValue)
        maxIterations -= 1
    End While

    Return original

End Function

0voto

Ich könnte ein regulären Ausdruck ersetzen mit einem look-around für diesen Fall verwenden.

Betrachten Sie dieses Beispiel:

Regex.Replace("FCCCF|CCC|CCC|", "((?<=[|])CCC(?=[|]))", "")
// ->
"FCCCF|||"

Dies wird immer die richtige Anzahl von Übereinstimmungen finden und ist nicht anfällig für mögliche Endlosschleifen. Es erfordert eine Anpassung des passenden regulären Ausdrucks und eine Änderung der Ersatzdaten.

Beachten Sie jedoch den Kommentar von Chris:

Regex.Replace("FCCCF|CCC|CCC||CCC|", "((?<=[|])CCC(?=[|]))", "")
// -> nur 5 Pipes: Stellen Sie sicher, dass dies den beabsichtigten Semantiken entspricht
"FCCCF|||||"

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X