Замінити останнє входження слова в рядок - C #


82

У мене проблема, коли мені потрібно замінити останнє входження слова в рядок.

Ситуація: Мені дається рядок у такому форматі:

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

Потім я замінюю TnaNameтаким чином:

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

Це працює, але у мене проблема, коли TnaNameтака сама, як і у мене folder name. Коли це трапляється, я в кінцевому підсумку отримую такий рядок:

F:/feb11/MFrame/Templates/feb11

Тепер він замінив обидва входження TnaNameз feb11. Чи є спосіб, яким я можу замінити лише останнє входження слова у свій рядок?

Примітка: feb11це те, TnaNameщо походить від іншого процесу - це не проблема.


Ваша єдина мета - замінити останню частину шляху? (тобто /відтепер?)
Саймон Уайтхед

Ніяка не остання частина repalce тільки остання TnaNameє більше у шляху, але я генерую лише зразок для питання. Дякую .
Шрі

1
Чи завжди цей рядок є шляхом до чогось? Подумайте про використання класу System.IO.Path, якщо він є.
Юрій Рожовецький

Так рядок завжди шлях до чогось.
Шрі

Відповіді:


179

Ось функція для заміни останнього входження рядка

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 це рядок, над яким потрібно виконати операцію.
  • Find це рядок, який ви хочете замінити.
  • Replace це рядок, яким ви хочете його замінити.

Велике спасибі за загальну функцію. Вона працює, і я також погоджуюсь з @Simon.
Шрі

6
будьте обережні, можливо, немає відповідності (тобто Place == -1)
Аліреза Ноорі

7
Можливо, логічніше повернути джерело, ніж порожній рядок, якщо збіг не знайдено.
Саша

2
Ви повинні повернути "return Source;" замість "повернути sting.Empty;" тому що його логічний збій, якщо не знайдено рядка пошуку.
Jignesh Variya

1
Додайте це між (і рядок Джерело як у: public static string ReplaceLastOccurance(this string Source...і у вас є чудовий метод розширення, який ви можете використати, щоб замінити останнє входження рядка для будь-якого рядка.
красивий

12

Використовуйте string.LastIndexOf()для пошуку індексу останнього входження рядка, а потім використовуйте підрядок для пошуку вашого рішення.


7

Ви повинні зробити заміну вручну:

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

3

Я не розумію, чому регулярний вираз не можна використовувати:

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

Використання:

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

1
Вам слід вказати значення Regex.Escape ().
jcox

Ви маєте на увазі return Regex.Replace(Regex.Replace(source),pattern, replacement);,?
toddmo

Припустимо, хтось викликає ReplaceEnd ("(foobar)", ")", "thenewend"). Ваша функція викине, оскільки ") $" є недійсним регулярним виразом. Це могло б спрацювати: return RegexReplace (source, Regex.Escape (value) + "$", replacement); Та сама історія для вашого RemoveEnd.
jcox

@jcox, я не міг зрозуміти, як уникнути подвійного виходу, b / c кожна функція є загальнодоступною, тому ми маємо кілька потенційних шляхів викликів. У моєму випадку я не використовував його для спеціальних символів, але я бачу вашу думку.
toddmo

@toddmo Я мав би ReplaceEnd та RemoveEnd викликати Regex. Замінювати безпосередньо. Хоча щось не в темі; Я просто хотів би, щоб люди усвідомлювали, що введення вводу користувача у шаблон регулярного виразу може бути складним. Подібно до введення вхідних даних у XML або SQL - тут повинен бути якийсь механізм виходу.
jcox

1

Ви можете використовувати Pathклас із System.IOпростору імен:

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

Console.WriteLine(System.IO.Path.GetDirectoryName(filePath));

0

Рішення може бути реалізоване ще простіше за допомогою одного рядка:

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

Цим ми користуємося жадібністю оператора зірочок регулярних виразів. Функція використовується так:

var s = "F:/feb11/MFrame/Templates/feb11";
var tnaName = "feb11";
var r = ReplaceLastOccurrence(s,tnaName, string.Empty);

0
var lastIndex = filePath.LastIndexOf(TnaName);

filePath = filePath.Substring(0, lastIndex);

2
Хоча відповіді лише на код можуть відповісти на питання, ви можете значно покращити якість своєї відповіді, надавши контекст для вашого коду, причину, чому цей код працює, та деякі посилання на документацію для подальшого читання. З " Як відповісти" : "Стислість прийнятна, але кращі пояснення кращі".
Pranav Hosangadi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.