Как заменить * первый экземпляр * строки в .NET?


108

Я хочу заменить первое вхождение в заданной строке.

Как я могу сделать это в .NET?


Пожалуйста, делайте четкие сообщения, понятные людям. Я тоже редактировал это для вас. Вы должны были указать язык хотя бы здесь.
GEOCHET

Конечно, он никогда не заменяется ... это всегда новая строка, содержащая исходную с замененным текстом. Это потому, что строки неизменяемы.
Пабло Марамбио

Я попробовал метод String.Replace (). но он заменяет все «AA» на «XQ»
Thorin Oakenshield

2
этот вопрос - stackoverflow.com/questions/141045/… - раскрывает все, что вам нужно сделать
stack72

1
Примечание: объединение с другим аналогичным вопросом, в котором в качестве примеров для поиска / замены использовалось «AA» => «XQ».
Марк Гравелл

Ответы:


134
string ReplaceFirst(string text, string search, string replace)
{
  int pos = text.IndexOf(search);
  if (pos < 0)
  {
    return text;
  }
  return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}

Пример:

string str = "The brown brown fox jumps over the lazy dog";

str = ReplaceFirst(str, "brown", "quick");

РЕДАКТИРОВАТЬ : как упоминалось в @itsmatt , есть также Regex.Replace (String, String, Int32), который может делать то же самое, но, вероятно, дороже во время выполнения, поскольку он использует полнофункциональный синтаксический анализатор, где мой метод выполняет одну находку и три строки конкатенации.

EDIT2 : если это обычная задача, вы можете сделать метод методом расширения:

public static class StringExtension
{
  public static string ReplaceFirst(this string text, string search, string replace)
  {
     // ...same as above...
  }
}

Используя приведенный выше пример, теперь можно написать:

str = str.ReplaceFirst("brown", "quick");

2
Интересно, вы проверили свое предположение о том, что подход регулярных выражений более дорог во время выполнения? Как насчет скорости? Возможно, поиск с использованием Regex быстрее, чем с помощью IndexOf?
mfloryan 05

Я предпочитаю ответ @BilltheLizard с участием Remove () и Insert () по сравнению с этим подходом с использованием Substring (). Есть ли основания утверждать, что одно лучше другого?
JohnC

3
Осторожно: это не работает должным образом с Unicode, объединяющим символы или лигатуры. Например, ReplaceFirst("oef", "œ", "i")неправильно возвращает «ief» вместо «if». См. Этот вопрос для получения дополнительной информации.
Майкл Лю

2
ReSharper предупреждает String.IndexOf is culture specific.. Более надежный для обновления до int pos = text.IndexOf(search, StringComparison.Ordinal);.
Contango,

64

Как itsmatt сказал Regex.Replace является хорошим выбором для этого , однако , чтобы сделать его ответ более полным , я заполню ее с образцом кода:

using System.Text.RegularExpressions;
...
Regex regex = new Regex("foo");
string result = regex.Replace("foo1 foo2 foo3 foo4", "bar", 1);             
// result = "bar1 foo2 foo3 foo4"

Третий параметр, установленный в 1 в этом случае, - это количество вхождений шаблона регулярного выражения, который вы хотите заменить во входной строке с начала строки.

Я надеялся, что это можно сделать с помощью статической перегрузки Regex.Replace, но, к сожалению, для этого вам нужен экземпляр Regex.


1
Это работает для буквального "foo", но вам понадобится new Regex(Regex.Escape("foo"))переносное "foo".
ruffin


15

С учетом «только первого», возможно:

int index = input.IndexOf("AA");
if (index >= 0) output = input.Substring(0, index) + "XQ" +
     input.Substring(index + 2);

?

Или в более общем плане:

public static string ReplaceFirstInstance(this string source,
    string find, string replace)
{
    int index = source.IndexOf(find);
    return index < 0 ? source : source.Substring(0, index) + replace +
         source.Substring(index + find.Length);
}

Затем:

string output = input.ReplaceFirstInstance("AA", "XQ");

11
using System.Text.RegularExpressions;

RegEx MyRegEx = new RegEx("F");
string result = MyRegex.Replace(InputString, "R", 1);

найти первый Fв InputStringи заменить его R.


2
Я упростил его до однострочного result = (New Regex("F")).Replace(InputString, "R", 1)
текста,

Лучший ответ здесь (в сочетании с cjbarth)
Тодд Вэнс

8

Метод расширения C #, который сделает это:

public static class StringExt
{
    public static string ReplaceFirstOccurrence(this string s, string oldValue, string newValue)
    {
         int i = s.IndexOf(oldValue);
         return s.Remove(i, oldValue.Length).Insert(i, newValue);    
    } 
}

наслаждаться


Спасибо! Я изменил это, чтобы создать метод расширения «RemoveFirst», который ... удаляет первое вхождение символа из строки.
pbh101

4
Это не удастся, если oldValue не является частью строки.
VVS

8

В синтаксисе C #:

int loc = original.IndexOf(oldValue);
if( loc < 0 ) {
    return original;
}
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);

4

И поскольку следует рассмотреть также VB.NET, я хотел бы предложить:

Private Function ReplaceFirst(ByVal text As String, ByVal search As String, ByVal replace As String) As String
    Dim pos As Integer = text.IndexOf(search)
    If pos >= 0 Then
        Return text.Substring(0, pos) + replace + text.Substring(pos + search.Length)
    End If
    Return text 
End Function

4

Предполагает, что его AAнужно заменить только в том случае, если он находится в самом начале строки:

var newString;
if(myString.StartsWith("AA"))
{
  newString ="XQ" + myString.Substring(2);
}

Если вам нужно заменить первое вхождение AA, независимо от того, начинается ли с него строка или нет, воспользуйтесь решением от Marc.


3

Одним из перегруженных Regex.Replaceпринимает intдля «максимального количества раз могут произойти замена». Очевидно, что использование Regex.Replaceдля замены обычного текста может показаться излишним, но оно определенно лаконично:

string output = (new Regex("AA")).Replace(input, "XQ", 1);

2

Для всех, кто не возражает против ссылки Microsoft.VisualBasic, есть ReplaceМетод :

string result = Microsoft.VisualBasic.Strings.Replace("111", "1", "0", 2, 1); // "101"

1

Этот пример абстрагирует подстроки (но работает медленнее), но, вероятно, намного быстрее, чем RegEx:

var parts = contents.ToString().Split(new string[] { "needle" }, 2, StringSplitOptions.None);
return parts[0] + "replacement" + parts[1];

0

Обновленный метод расширения, Spanпозволяющий минимизировать создание новой строки

    public static string ReplaceFirstOccurrence(this string source, string search, string replace) {
        int index = source.IndexOf(search);
        if (index < 0) return source;
        var sourceSpan = source.AsSpan();
        return string.Concat(sourceSpan.Slice(0, index), replace, sourceSpan.Slice(index + search.Length));
    }

-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.