J'ai besoin d'un moyen d'avoir ceci:
"test, and test but not testing. But yes to test".Replace("test", "text")
retournez ceci:
"text, and text but not testing. But yes to text"
En gros, je veux remplacer les mots entiers, mais pas les correspondances partielles.
REMARQUE: je vais devoir utiliser VB pour cela (code SSRS 2008), mais C # est mon langage normal. Les réponses dans les deux cas sont correctes.
Une expression régulière est l'approche la plus simple:
string input = "test, and test but not testing. But yes to test";
string pattern = @"\btest\b";
string replace = "text";
string result = Regex.Replace(input, pattern, replace);
Console.WriteLine(result);
La partie importante du motif est le métacaractère \b
, qui correspond aux limites de Word. Si vous en avez besoin, utilisez la méthode RegexOptions.IgnoreCase
:
Regex.Replace(input, pattern, replace, RegexOptions.IgnoreCase);
J'ai créé une fonction (voir billet de blog ici ) qui enveloppe l'expression regex, suggérée par Ahmad Mageed
/// <summary>
/// Uses regex '\b' as suggested in https://stackoverflow.com/questions/6143642/way-to-have-string-replace-only-hit-whole-words
/// </summary>
/// <param name="original"></param>
/// <param name="wordToFind"></param>
/// <param name="replacement"></param>
/// <param name="regexOptions"></param>
/// <returns></returns>
static public string ReplaceWholeWord(this string original, string wordToFind, string replacement, RegexOptions regexOptions = RegexOptions.None)
{
string pattern = String.Format(@"\b{0}\b", wordToFind);
string ret=Regex.Replace(original, pattern, replacement, regexOptions);
return ret;
}
Comme l'a commenté Sga, la solution regex n'est pas parfaite. Et je suppose que la performance n’est pas favorable non plus.
Voici ma contribution:
public static class StringExtendsionsMethods
{
public static String ReplaceWholeWord ( this String s, String Word, String bywhat )
{
char firstLetter = Word[0];
StringBuilder sb = new StringBuilder();
bool previousWasLetterOrDigit = false;
int i = 0;
while ( i < s.Length - Word.Length + 1 )
{
bool wordFound = false;
char c = s[i];
if ( c == firstLetter )
if ( ! previousWasLetterOrDigit )
if ( s.Substring ( i, Word.Length ).Equals ( Word ) )
{
wordFound = true;
bool wholeWordFound = true;
if ( s.Length > i + Word.Length )
{
if ( Char.IsLetterOrDigit ( s[i+Word.Length] ) )
wholeWordFound = false;
}
if ( wholeWordFound )
sb.Append ( bywhat );
else
sb.Append ( Word );
i += Word.Length;
}
if ( ! wordFound )
{
previousWasLetterOrDigit = Char.IsLetterOrDigit ( c );
sb.Append ( c );
i++;
}
}
if ( s.Length - i > 0 )
sb.Append ( s.Substring ( i ) );
return sb.ToString ();
}
}
... Avec cas de test:
String a = "alpha is alpha";
Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "alphonse" ) );
Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "alf" ) );
a = "alphaisomega";
Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "xxx" ) );
a = "aalpha is alphaa";
Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "xxx" ) );
a = "alpha1/alpha2/alpha3";
Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "xxx" ) );
a = "alpha/alpha/alpha";
Console.WriteLine ( a.ReplaceWholeWord ( "alpha", "alphonse" ) );
Je veux juste ajouter une note sur ce motif de regex particulier (utilisé à la fois dans la réponse acceptée et dans la fonction ReplaceWholeWord) . Cela ne fonctionne pas si ce que vous essayez de remplacer n'est pas un Word.
Voici un cas de test:
using System;
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
string input = "doin' some replacement";
string pattern = @"\bdoin'\b";
string replace = "doing";
string result = Regex.Replace(input, pattern, replace);
Console.WriteLine(result);
}
}
(prêt à essayer le code: http://ideone.com/2Nt0A )
Ceci doit être pris en compte spécialement si vous effectuez des traductions par lots (comme je l’ai fait pour certains travaux de i18n).
Si vous voulez définir quels caractères constituent un mot, c'est-à-dire "_" et "@"
vous pouvez utiliser ma fonction (vb.net):
Function Replace_Whole_Word(Input As String, Find As String, Replace As String)
Dim Word_Chars As String = "ABCDEFGHIJKLMNOPQRSTUVWYXZabcdefghijklmnopqrstuvwyxz0123456789_@"
Dim Word_Index As Integer = 0
Do Until False
Word_Index = Input.IndexOf(Find, Word_Index)
If Word_Index < 0 Then Exit Do
If Word_Index = 0 OrElse Word_Chars.Contains(Input(Word_Index - 1)) = False Then
If Word_Index + Len(Find) = Input.Length OrElse Word_Chars.Contains(Input(Word_Index + Len(Find))) = False Then
Input = Mid(Input, 1, Word_Index) & Replace & Mid(Input, Word_Index + Len(Find) + 1)
End If
End If
Word_Index = Word_Index + 1
Loop
Return Input
End Function
Test
Replace_Whole_Word("We need to replace words tonight. Not to_day and not too well to", "to", "xxx")
Résultat
"We need xxx replace words tonight. Not to_day and not too well xxx"