Ersetzen Sie das letzte Vorkommen eines Wortes in einer Zeichenfolge - C #

82

Ich habe ein Problem, bei dem ich das letzte Vorkommen eines Wortes in einer Zeichenfolge ersetzen muss.

Situation: Ich erhalte eine Zeichenfolge in diesem Format:

string filePath ="F:/jan11/MFrame/Templates/feb11";

Ich ersetze dann TnaNameso:

filePath = filePath.Replace(TnaName, ""); // feb11 is TnaName

Das funktioniert, aber ich habe ein Problem, wenn TnaNamees dasselbe ist wie meins folder name. Wenn dies passiert, bekomme ich eine Zeichenfolge wie die folgende:

F:/feb11/MFrame/Templates/feb11

Jetzt hat es beide Vorkommen von TnaNamedurch ersetzt feb11. Gibt es eine Möglichkeit, nur das letzte Vorkommen des Wortes in meiner Zeichenfolge zu ersetzen?

Hinweis: feb11ist TnaNamedie von einem anderen Prozess kommt - das ist kein Problem.

Shree
quelle
Ist Ihr einziges Ziel, den letzten Teil des Pfades zu ersetzen? (Das heißt, von nun /an?)
Simon Whitehead
Nein, nicht ein letzter Teil repalce nur zuletzt TnaNamegibt es mehr im Pfad, aber ich generiere nur Probe für Frage. Danke .
Shree
1
Ist diese Zeichenfolge immer ein Pfad zu etwas? Verwenden Sie gegebenenfalls die Klasse System.IO.Path.
Yuriy Rozhovetskiy
Ja String immer ein Pfad zu etwas.
Shree

Antworten:

175

Hier ist die Funktion zum Ersetzen des letzten Auftretens einer Zeichenfolge

public static string ReplaceLastOccurrence(string Source, string Find, string Replace)
{
        int place = Source.LastIndexOf(Find);

        if(place == -1)
           return Source;

        string result = Source.Remove(place, Find.Length).Insert(place, Replace);
        return result;
}
  • Source ist die Zeichenfolge, für die Sie die Operation ausführen möchten.
  • Find ist die Zeichenfolge, die Sie ersetzen möchten.
  • Replace ist die Zeichenfolge, durch die Sie sie ersetzen möchten.
Behroz Sikander
quelle
Vielen Dank für die generische Funktion. Es funktioniert und ich stimme auch @Simon zu.
Shree
6
Vorsicht, vielleicht gibt es keine Übereinstimmung (dh Place == -1)
Alireza Noori
7
Es ist wahrscheinlich logischer, die Quelle zurückzugeben als eine leere Zeichenfolge, falls keine Übereinstimmung gefunden wird.
Sasha
2
Sie sollten "return Source" zurückgeben. anstelle von "return sting.Empty;" weil seine Logik fehlgeschlagen ist, wenn kein Vorkommen von Find string gefunden wurde.
Jignesh Variya
1
Fügen Sie dies zwischen (und Zeichenfolge Source wie in: hinzu, public static string ReplaceLastOccurance(this string Source...und Sie haben eine raffinierte Erweiterungsmethode, mit der Sie das letzte Vorkommen einer Zeichenfolge für eine beliebige Zeichenfolge ersetzen können.
Beaudetious
12

Verwenden Sie string.LastIndexOf()diese Option , um den Index des letzten Vorkommens der Zeichenfolge zu ermitteln, und verwenden Sie dann die Teilzeichenfolge, um nach Ihrer Lösung zu suchen.

Montycarlo
quelle
7

Sie müssen das Ersetzen manuell durchführen:

int i = filePath.LastIndexOf(TnaName);
if (i >= 0)
    filePath = filePath.Substring(0, i) + filePath.Substring(i + TnaName.Length);
Mohammad Dehghan
quelle
3

Ich verstehe nicht, warum Regex nicht verwendet werden kann:

public static string RegexReplace(this string source, string pattern, string replacement)
{
  return Regex.Replace(source,pattern, replacement);
}

public static string ReplaceEnd(this string source, string value, string replacement)
{
  return RegexReplace(source, $"{value}$", replacement);
}

public static string RemoveEnd(this string source, string value)
{
  return ReplaceEnd(source, value, string.Empty);
}

Verwendung:

string filePath ="F:/feb11/MFrame/Templates/feb11";
filePath = filePath.RemoveEnd("feb11"); // F:/feb11/MFrame/Templates/
filePath = filePath.ReplaceEnd("feb11","jan11"); // F:/feb11/MFrame/Templates/jan11
toddmo
quelle
1
Sie sollten den Wert Regex.Escape () verwenden.
JCox
Du meinst return Regex.Replace(Regex.Replace(source),pattern, replacement);?
Toddmo
Angenommen, jemand ruft ReplaceEnd ("(foobar)", ")", "thenewend") auf. Ihre Funktion wird werfen, weil ") $" eine ungültige Regex ist. Dies würde funktionieren: return RegexReplace (Quelle, Regex.Escape (Wert) + "$", Ersatz); Gleiche Geschichte für Ihr RemoveEnd.
JCox
@jcox, ich konnte nicht herausfinden, wie man Doppel-Escape-Aktionen vermeidet. Da jede Funktion öffentlich ist, haben wir mehrere potenzielle Aufrufpfade. In meinem Fall habe ich es nicht für Sonderzeichen verwendet, aber ich verstehe Ihren Standpunkt.
Toddmo
@toddmo Ich hätte ReplaceEnd und RemoveEnd, um Regex.Replace direkt aufzurufen. Ein bisschen abseits des Themas; Ich möchte nur, dass die Leute wissen, dass das Einfügen von Benutzereingaben in ein Regex-Muster schwierig sein kann. Ähnlich wie beim Einfügen von Eingaben in XML oder SQL muss ein Escape-Mechanismus vorhanden sein.
JCox
1

Sie können eine PathKlasse aus dem System.IONamespace verwenden:

string filePath = "F:/jan11/MFrame/Templates/feb11";

Console.WriteLine(System.IO.Path.GetDirectoryName(filePath));
Yuriy Rozhovetskiy
quelle
0

Die Lösung kann mit einer einzigen Zeile noch einfacher implementiert werden:

 static string ReplaceLastOccurrence(string str, string toReplace, string replacement)
    {
        return Regex.Replace(str, $@"^(.*){toReplace}(.*?)$", $"$1{replacement}$2");
    }

Hierbei nutzen wir die Gier des Regex-Sternchen-Operators. Die Funktion wird folgendermaßen verwendet:

var s = "F:/feb11/MFrame/Templates/feb11";
var tnaName = "feb11";
var r = ReplaceLastOccurrence(s,tnaName, string.Empty);
MarcBalta
quelle
0
var lastIndex = filePath.LastIndexOf(TnaName);

filePath = filePath.Substring(0, lastIndex);
Kai Hartmann
quelle
1
Während Antworten nur mit Code die Frage beantworten können, können Sie die Qualität Ihrer Antwort erheblich verbessern, indem Sie den Kontext für Ihren Code, einen Grund für die Funktionsweise dieses Codes und einige Verweise auf die Dokumentation zur weiteren Lektüre angeben. Aus der Antwort : "Kürze ist akzeptabel, aber ausführlichere Erklärungen sind besser."
Pranav Hosangadi