Comment remplacer la * première instance * d'une chaîne dans .NET?

108

Je veux remplacer la première occurrence dans une chaîne donnée.

Comment puis-je accomplir cela dans .NET?

Au revoir StackExchange
la source
Veuillez publier des messages clairs que les gens peuvent comprendre. J'ai aussi édité celui-ci pour vous. Vous devriez avoir spécifié une langue au moins ici.
GEOCHET
Bien sûr, elle n'est jamais remplacée ... c'est toujours une nouvelle chaîne contenant l'original avec du texte remplacé. C'est parce que les chaînes sont immuables.
Pablo Marambio
J'ai essayé la méthode `String.Replace ()`. mais il remplace tous les "AA" par "XQ"
Thorin Oakenshield
2
cette question - stackoverflow.com/questions/141045/… - révèle tout ce que vous devez faire
stack72
1
Remarque: fusion avec une autre question similaire qui utilisait "AA" => "XQ" comme exemples à rechercher / remplacer.
Marc Gravell

Réponses:

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

Exemple:

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

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

EDIT : Comme @itsmatt l'a mentionné , il y a aussi Regex.Replace (String, String, Int32), qui peut faire la même chose, mais est probablement plus cher à l'exécution, car il utilise un analyseur complet où ma méthode fait une recherche et trois chaînes concaténations.

EDIT2 : S'il s'agit d'une tâche courante, vous souhaiterez peut-être faire de la méthode une méthode d'extension:

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

En utilisant l'exemple ci-dessus, il est maintenant possible d'écrire:

str = str.ReplaceFirst("brown", "quick");
VVS
la source
2
Intéressant, avez-vous testé votre hypothèse selon laquelle l'approche regex est plus chère à l'exécution? Et la vitesse? Peut-être que la recherche avec Regex est plus rapide qu'avec IndexOf?
mfloryan le
Je préfère un peu la réponse de @BilltheLizard impliquant Remove () et Insert () à cette approche impliquant Substring (). Y a-t-il une raison de dire que l'un est meilleur que l'autre?
JohnC
3
Attention: cela ne fonctionne pas correctement avec Unicode combinant des caractères ou des ligatures. Par exemple, ReplaceFirst("oef", "œ", "i")renvoie incorrectement "ief" au lieu de "if". Voir cette question pour plus d'informations.
Michael Liu
2
ReSharper prévient String.IndexOf is culture specific.. Plus robuste à mettre à jour int pos = text.IndexOf(search, StringComparison.Ordinal);.
Contango
64

Comme itsmatt l'a dit Regex.Replace est un bon choix pour cela, mais pour rendre sa réponse plus complète, je vais la compléter avec un exemple de code:

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

Le troisième paramètre, défini sur 1 dans ce cas, est le nombre d'occurrences du modèle regex que vous souhaitez remplacer dans la chaîne d'entrée à partir du début de la chaîne.

J'espérais que cela pourrait être fait avec une surcharge statique Regex.Replace mais malheureusement, il semble que vous ayez besoin d'une instance Regex pour l'accomplir.

Wes Haggard
la source
1
Cela fonctionne pour le littéral "foo", mais vous allez vouloir un new Regex(Regex.Escape("foo"))pour le figuratif "foo".
ruffin
17

Jetez un œil à Regex.Replace .

itsmatt
la source
2
Plus précisément, la méthode Regex.Replace (String, String, Int32) fera l'affaire et est vraiment concise.
itsmatt le
15

En tenant compte du «premier seulement», peut-être:

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

?

Ou plus généralement:

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

Ensuite:

string output = input.ReplaceFirstInstance("AA", "XQ");
Marc Gravell
la source
11
using System.Text.RegularExpressions;

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

trouvera le premier Fdans InputStringet le remplacera par R.

Deenesh
la source
2
Je l'ai simplifié en un one-liner parresult = (New Regex("F")).Replace(InputString, "R", 1)
cjbarth
Meilleure réponse ici (en collaboration avec cjbarth)
Todd Vance
8

Méthode d'extension C # qui fera ceci:

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

Prendre plaisir

Mortenbpost
la source
Merci! J'ai modifié cela pour créer une méthode d'extension "RemoveFirst" qui ... supprime la première occurrence d'un caractère d'une chaîne.
pbh101
4
Cela échouera si oldValue ne fait pas partie de la chaîne.
VVS
8

Dans la syntaxe C #:

int loc = original.IndexOf(oldValue);
if( loc < 0 ) {
    return original;
}
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);
Bill le lézard
la source
4

Et comme il y a aussi VB.NET à considérer, je voudrais offrir:

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
Anthony Potts
la source
4

Suppose qu'il AAne doit être remplacé que s'il se trouve au tout début de la chaîne:

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

Si vous devez remplacer la première occurrence de AA, que la chaîne commence par elle ou non, optez pour la solution de Marc.

Oded
la source
3

Une des surcharges de Regex.Replaceprend un intpour "Le nombre maximum de fois que le remplacement peut se produire". Évidemment, utiliser Regex.Replacepour le remplacement de texte brut peut sembler exagéré, mais c'est certainement concis:

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

Pour tous ceux qui ne se soucient pas d'une référence Microsoft.VisualBasic, il y a la Replaceméthode :

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

Cet exemple résume les sous-chaînes (mais est plus lent), mais est probablement beaucoup plus rapide qu'un RegEx:

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

la source
0

Mise à jour de la méthode d'extension permettant Spande minimiser la création de nouvelles chaînes

    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));
    }
Brad Patton
la source
-1
string abc = "AAAAX1";

            if(abc.IndexOf("AA") == 0)
            {
                abc.Remove(0, 2);
                abc = "XQ" + abc;
            }

la source