Заменить только 'n' вхождения подстроки в строке в C # - PullRequest
0 голосов
/ 22 марта 2019

У меня есть строка ввода, как -

abbdabab

Как заменить только 2-й , 3-й и последующих вхождений подстроки "ab" любой случайной строкой, такой как "x", с сохранением исходной строки неповрежденными. Пример в этом случае -

1-й вывод - xbdabab 2-й вывод - abbdxab 3-й вывод - abbdabx и т. Д ...

Я пытался использовать Regex, как -

int occCount = Regex.Matches("abbdabab", "ab").Count;

if (occCount > 1)
{
    for (int i = 1; i <= occCount; i++)
    {
        Regex regReplace = new Regex("ab");
        string modifiedValue = regReplace.Replace("abbdabab", "x", i);
        //decodedMessages.Add(modifiedValue);
    }
 }

Здесь я могу получить 1-й выход, когда значение счетчика i равно 1, но не могу получить последующие результаты. Есть ли какой-нибудь метод перегруженный Replace, который мог бы достичь этого? Или кто-нибудь может помочь мне указать, где я мог ошибиться?

Ответы [ 3 ]

2 голосов
/ 22 марта 2019

Вы можете попробовать IndexOf вместо регулярных выражений:

string source = "abbdabab";
string toFind = "ab";
string toSet = "X";

for (int index = source.IndexOf(toFind); 
     index >= 0; 
     index = source.IndexOf(toFind, index + 1)) {
  string result = source.Substring(0, index) + 
                  toSet + 
                  source.Substring(index + toFind.Length);

  Console.WriteLine(result);
}

Результат:

Xbdabab
abbdXab
abbdabX
1 голос
/ 22 марта 2019

Вы можете использовать StringBuilder:

string s = "abbdabab";
var matches = Regex.Matches(s, "ab");
StringBuilder sb = new StringBuilder(s);
var m = matches[0]; // 0 for first output, 1 for second output, and so on
sb.Remove(m.Index, m.Length);
sb.Insert(m.Index, "x");
var result = sb.ToString();
Console.WriteLine(result);
0 голосов
/ 22 марта 2019

Вы можете использовать динамически построенное регулярное выражение для непосредственного использования с regex.Replace:

var s = "abbdabab";
var idx = 1; // First = 1, Second = 2
var search = "ab";
var repl = "x";
var pat = new Regex($@"(?s)((?:{search}.*?){{{idx-1}}}.*?){search}"); // ((?:ab.*?){0}.*?)ab
Console.WriteLine(pat.Replace(s, $"${{1}}{repl}", 1));

См. Демонстрацию C #

Шаблон будет выглядеть как ((?:ab.*?){0}.*?)ab и будет соответствовать

  • (?s) - RegexOptions.Singleline, чтобы . также совпадал с новыми строками
  • ((?:ab.*?){0}.*?) - группа 1 (позже это значение будет возвращенов результат с ${1} обратная ссылка)
    • (?:ab.*?){0} - 0 экземпляров ab, за которыми следуют любые 0+ символов как можно меньше
    • .*? - любые 0+ символов каккак можно меньше
  • ab - строка / шаблон поиска.

Последний аргумент pat.Replace - 1, так что толькоПервое вхождение может быть заменено.

Если search является литеральным текстом, вам нужно использовать var search = Regex.Escape("a+b");.

Если repl может иметь $, добавьте repl = repl.Replace("$", "$$");.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...