我需要一种方法来做到这一点:
"test, and test but not testing. But yes to test".Replace("test", "text")
返回此:
"text, and text but not testing. But yes to text"
基本上我想替换整个单词,而不是部分匹配。
注意:为此,我将不得不使用VB(SSRS 2008代码),但是C#是我的常规语言,因此使用两种方法都可以。
我需要一种方法来做到这一点:
"test, and test but not testing. But yes to test".Replace("test", "text")
返回此:
"text, and text but not testing. But yes to text"
基本上我想替换整个单词,而不是部分匹配。
注意:为此,我将不得不使用VB(SSRS 2008代码),但是C#是我的常规语言,因此使用两种方法都可以。
Answers:
正则表达式是最简单的方法:
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);
模式的重要部分是\b
元字符,它在单词边界上匹配。如果您需要不区分大小写,请使用RegexOptions.IgnoreCase
:
Regex.Replace(input, pattern, replace, RegexOptions.IgnoreCase);
\b
正则表达式在哪里代表单词边界。
static string ReplaceFullWords( string input, string from, string to) { if (input == null) { return null; } return Regex.Replace(input, "\\b" + Regex.Escape(from) + "\\b", to); }
string pattern = "\\btest\\b";
我创建了一个包装正则表达式的函数(请参见博客文章),由Ahmad Mageed建议
/// <summary>
/// Uses regex '\b' as suggested in /programming/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;
}
Regex.Escape()
,wordToFind
以便将特殊字符解释为常规字符。
正如Sga所说,正则表达式解决方案并不完美。而且我想也不是性能友好的。
这是我的贡献:
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 ();
}
}
...带有测试用例:
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" ) );
我只想添加关于此特定正则表达式模式的注释(用于接受的答案和ReplaceWholeWord函数中)。如果您要替换的单词不是一个单词,那是行不通的。
这里是一个测试案例:
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);
}
}
(可以尝试使用的代码:http : //ideone.com/2Nt0A)
特别是如果您要进行批处理翻译时(例如我在某些i18n工作中所做的),则必须考虑到这一点。
如果要定义什么字符组成一个单词,即“ _”和“ @”
您可以使用我的(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
测试
Replace_Whole_Word("We need to replace words tonight. Not to_day and not too well to", "to", "xxx")
结果
"We need xxx replace words tonight. Not to_day and not too well xxx"
我不喜欢Regex,因为它运行缓慢。我的功能更快。
public static string ReplaceWholeWord(this string text, string word, string bywhat)
{
static bool IsWordChar(char c) => char.IsLetterOrDigit(c) || c == '_';
StringBuilder sb = null;
int p = 0, j = 0;
while (j < text.Length && (j = text.IndexOf(word, j, StringComparison.Ordinal)) >= 0)
if ((j == 0 || !IsWordChar(text[j - 1])) &&
(j + word.Length == text.Length || !IsWordChar(text[j + word.Length])))
{
sb ??= new StringBuilder();
sb.Append(text, p, j - p);
sb.Append(bywhat);
j += word.Length;
p = j;
}
else j++;
if (sb == null) return text;
sb.Append(text, p, text.Length - p);
return sb.ToString();
}