Como substituo a * primeira instância * de uma string no .NET?


108

Quero substituir a primeira ocorrência em uma determinada string.

Como posso fazer isso no .NET?


Por favor, deixe postagens claras que as pessoas possam entender. Eu editei este para você também. Você deve ter especificado um idioma pelo menos aqui.
GEOCHET

Claro, ele nunca é substituído ... é sempre uma nova string contendo o original com o texto substituído. Isso ocorre porque as strings são imutáveis.
Pablo Marambio

Tentei o método `String.Replace ()`. mas substitui todos os "AA" por "XQ"
Thorin Oakenshield

2
esta pergunta - stackoverflow.com/questions/141045/… - revela tudo sobre o que você precisa fazer
stack72

1
Nota: mesclando com outra pergunta semelhante que usava "AA" => "XQ" como exemplos para localizar / substituir.
Marc Gravell

Respostas:


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

Exemplo:

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

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

EDIT : Como @itsmatt mencionou , há também Regex.Replace (String, String, Int32), que pode fazer o mesmo, mas provavelmente é mais caro em tempo de execução, já que está utilizando um analisador completo onde meu método faz um find e três strings concatenações.

EDIT2 : Se esta é uma tarefa comum, você pode querer tornar o método um método de extensão:

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

Usando o exemplo acima, agora é possível escrever:

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

2
Interessante, você testou sua suposição sobre a abordagem de regex ser mais cara em tempo de execução? Que tal velocidade? Talvez a pesquisa usando Regex seja mais rápida do que usando IndexOf?
mfloryan

Eu meio que prefiro a resposta de @BilltheLizard envolvendo Remove () e Insert () a esta abordagem envolvendo Substring (). Existe alguma base para dizer que um é melhor do que o outro?
JohnC de

3
Cuidado: isso não funciona corretamente com Unicode combinando caracteres ou ligaduras. Por exemplo, ReplaceFirst("oef", "œ", "i")retorna incorretamente "ief" em vez de "if". Veja esta pergunta para mais informações.
Michael Liu

2
ReSharper avisa String.IndexOf is culture specific.. Mais robusto para atualizar int pos = text.IndexOf(search, StringComparison.Ordinal);.
Contango

64

Como itsmatt disse, Regex.Replace é uma boa escolha para isso, porém, para tornar sua resposta mais completa, vou preenchê-la com um exemplo de código:

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

O terceiro parâmetro, definido como 1 neste caso, é o número de ocorrências do padrão regex que você deseja substituir na string de entrada desde o início da string.

Eu esperava que isso pudesse ser feito com uma sobrecarga estática de Regex.Replace, mas, infelizmente, parece que você precisa de uma instância de Regex para fazer isso.


1
Isso funciona para o literal "foo", mas você vai querer um new Regex(Regex.Escape("foo"))para o figurativo "foo".
ruffin


15

Levando o "primeiro apenas" em consideração, talvez:

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

?

Ou mais geralmente:

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

Então:

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

11
using System.Text.RegularExpressions;

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

irá encontrar primeiro Fem InputStringe substituí-lo por R.


2
Eu simplifiquei para uma linha porresult = (New Regex("F")).Replace(InputString, "R", 1)
cjbarth

Melhor resposta aqui (em conjunto com cjbarth)
Todd Vance

8

Método de extensão C # que fará isso:

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

Aproveitar


Obrigado! Eu modifiquei isso para fazer um método de extensão "RemoveFirst" que ... remove a primeira ocorrência de um caractere de uma string.
pbh101

4
Isso falhará se oldValue não fizer parte da string.
VVS

8

Na sintaxe C #:

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

4

E porque também há VB.NET a considerar, eu gostaria de oferecer:

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

Presume que AAsó precisa ser substituído se estiver no início da string:

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

Se você precisar substituir a primeira ocorrência de AA, quer a string comece com ele ou não, vá com a solução de Marc.


3

Uma das sobrecargas de Regex.Replaceleva um intpara "O número máximo de vezes que a substituição pode ocorrer". Obviamente, usar Regex.Replacepara substituição de texto simples pode parecer um exagero, mas certamente é conciso:

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

2

Para quem não se importa com uma referência Microsoft.VisualBasic, existe o ReplaceMétodo :

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

1

Este exemplo abstrai as substrings (mas é mais lento), mas provavelmente é muito mais rápido do que um RegEx:

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

-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.