Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何忽略String.replace中的大小写_C#_String_Replace_Ignore Case - Fatal编程技术网

C# 如何忽略String.replace中的大小写

C# 如何忽略String.replace中的大小写,c#,string,replace,ignore-case,C#,String,Replace,Ignore Case,如何将句子中的“camel”替换为“horse”,尽管有字符串。replace不支持左字符串上的ignoreCase?使用正则表达式: string sentence = "We know it contains 'camel' word."; // Camel can be in different cases: string s1 = "CAMEL"; string s2 = "CaMEL"; string s3 = "CAMeL"; // ... string s4 = "Camel";

如何将句子中的“camel”替换为“horse”,尽管有
字符串。replace
不支持左字符串上的
ignoreCase

使用正则表达式:

string sentence = "We know it contains 'camel' word.";
// Camel can be in different cases:
string s1 = "CAMEL";
string s2 = "CaMEL";
string s3 = "CAMeL";
// ...
string s4 = "Camel";
// ...
string s5 = "camel";
当然,这也将匹配包含camel的单词,但不清楚您是否希望这样

如果需要精确匹配,可以使用自定义MatchEvaluator

var regex = new Regex( "camel", RegexOptions.IgnoreCase );
var newSentence = regex.Replace( sentence, "horse" );
与上一个示例一起使用,将匹配项包装为一个范围:

public static class Evaluators
{
    public static string Wrap( Match m, string original, string format )
    {
        // doesn't match the entire string, otherwise it is a match
        if (m.Length != original.Length)
        {
            // has a preceding letter or digit (i.e., not a real match).
            if (m.Index != 0 && char.IsLetterOrDigit( original[m.Index - 1] ))
            {
                return m.Value;
            }
            // has a trailing letter or digit (i.e., not a real match).
            if (m.Index + m.Length != original.Length && char.IsLetterOrDigit( original[m.Index + m.Length] ))
            {
                return m.Value;
            }
        }
        // it is a match, apply the format
        return string.Format( format, m.Value );
    }
} 
var regex=new regex(highlightedWord,RegexOptions.IgnoreCase);
foreach(句子中的var语句)
{
var evaluator=newmatchevaluator(match=>Evaluators.Wrap(匹配,句子,{0}));
Console.WriteLine(regex.Replace(句子,求值符));
}

您也可以使用String.IndexOf


这样做可能会比使用正则表达式获得更好的性能(我讨厌它们,因为它们不直观,也不容易出错,尽管这个简单的.Net函数调用抽象了实际混乱的正则表达式,并且没有提供太多的出错空间),但这可能不是您关心的问题;现在计算机真的很快,对吗?:)采用StringComparison对象的IndexOf重载允许您选择性地忽略大小写,并且由于IndexOf从指定位置返回第一个匹配项,您必须对循环进行编码,以处理多次出现的字符串。

使用
StringComparison
,因为它非常方便
OrdinalIgnoreCase

var regex = new Regex( highlightedWord, RegexOptions.IgnoreCase );
foreach (var sentence in sentences)
{
    var evaluator = new MatchEvaluator( match => Evaluators.Wrap( match, sentence, "<span class='red'>{0}</span>" ) );
    Console.WriteLine( regex.Replace( sentence, evaluator ) );
}

如果C#String类有一个类似Java的
ignoreCase()
方法,那当然好了。

为String添加一个扩展方法来实现这一点:

用法:

    string sentence = "We know it contains 'camel' word."; 
    string wordToFind = "camel";
    string replacementWord = "horse";

    int index = sentence.IndexOf(wordToFind , StringComparison.OrdinalIgnoreCase)
    // Did we match the word regardless of case
    bool match = index >= 0;

    // perform the replace on the matched word
    if(match) {
        sentence = sentence.Remove(index, wordToFind.Length)
        sentence = sentence.Insert(index, replacementWord)
    }
public static string Replace(this string source, string oldString, 
                             string newString, StringComparison comparison)
{
    int index = source.IndexOf(oldString, comparison);

    while (index > -1)
    {
        source = source.Remove(index, oldString.Length);
        source = source.Insert(index, newString);

        index = source.IndexOf(oldString, index + newString.Length, comparison);
    }

    return source;
}
public static string Replace(this string source, string oldString, 
                             string newString, StringComparison comparison,
                             bool recursive = true)
{
    int index = source.IndexOf(oldString, comparison);

    while (index > -1)
    {
        source = source.Remove(index, oldString.Length);
        source = source.Insert(index, newString);

        if (!recursive)
        {
            return source;
        }
        index = source.IndexOf(oldString, index + newString.Length, comparison);
    }

    return source;
}
代码:


它可能没有其他一些答案那么有效,但我有点喜欢sntbob编写的CustomReplace函数

然而,它有一个缺陷。如果文本替换是递归的,它将导致无限循环。例如,CustomReplace(“我吃香蕉!”,“an”,“banana”,false,false)将导致无限循环,字符串将继续变大。 例如,在第四次迭代之后,字符串将是“我吃BBBBB anaanaanaas!”

如果您只想在“香蕉”中替换“an”的两个实例,那么您必须采取另一种方法。我修改了sntbob的代码来解释这个案例。我承认它要复杂得多,但它可以处理递归替换

    public static string CustomReplace(string srcText, string toFind, string toReplace, bool matchCase, bool replace0nce)
    {
        StringComparison sc = StringComparison.OrdinalIgnoreCase;
        if (matchCase)
            sc = StringComparison.Ordinal;

        int pos;
        while ((pos = srcText.IndexOf(toFind, sc)) > -1)
        {
            srcText = srcText.Remove(pos, toFind.Length);
            srcText = srcText.Insert(pos, toReplace);

            if (replace0nce)
                break;
        }

        return srcText;
    }

下面是一个使用string.IndexOf进行StringComparison的扩展方法:

public static string CustomReplace(string srcText, string toFind, string toReplace, bool matchCase, bool replaceOnce)
    {
        StringComparison sc = StringComparison.OrdinalIgnoreCase;
        if (matchCase)
            sc = StringComparison.Ordinal;

        int pos;
        int previousProcessedLength = 0;
        string alreadyProcessedTxt = "";
        string remainingToProcessTxt = srcText;
        while ((pos = remainingToProcessTxt.IndexOf(toFind, sc)) > -1)
        {
            previousProcessedLength = alreadyProcessedTxt.Length;
            //Append processed text up until the end of the found string and perform replacement
            alreadyProcessedTxt += remainingToProcessTxt.Substring(0, pos + toFind.Length);
            alreadyProcessedTxt = alreadyProcessedTxt.Remove(previousProcessedLength + pos, toFind.Length);
            alreadyProcessedTxt = alreadyProcessedTxt.Insert(previousProcessedLength + pos, toReplace);

            //Remove processed text from remaining
            remainingToProcessTxt = remainingToProcessTxt.Substring(pos + toFind.Length);                

            if (replaceOnce)
                break;
        }

        return alreadyProcessedTxt + remainingToProcessTxt;
    }
顺便说一句,这里还有一个类似的Contains方法,也进行了StringComparison:

    [Pure]
    public static string Replace(this string source, string oldValue, string newValue, StringComparison comparisonType)
    {
        if (source.Length == 0 || oldValue.Length == 0)
            return source;

        var result = new System.Text.StringBuilder();
        int startingPos = 0;
        int nextMatch;
        while ((nextMatch = source.IndexOf(oldValue, startingPos, comparisonType)) > -1)
        {
            result.Append(source, startingPos, nextMatch - startingPos);
            result.Append(newValue);
            startingPos = nextMatch + oldValue.Length;
        }
        result.Append(source, startingPos, source.Length - startingPos);

        return result.ToString();
    }
一些测试:

    [Pure]
    public static bool Contains(this string source, string value, StringComparison comparisonType)
    {
        return source.IndexOf(value, comparisonType) >= 0;
    }

这是我的扩展方法,它结合了的递归性和对指出的错误的更清晰的修复

代码:

用法:

    string sentence = "We know it contains 'camel' word."; 
    string wordToFind = "camel";
    string replacementWord = "horse";

    int index = sentence.IndexOf(wordToFind , StringComparison.OrdinalIgnoreCase)
    // Did we match the word regardless of case
    bool match = index >= 0;

    // perform the replace on the matched word
    if(match) {
        sentence = sentence.Remove(index, wordToFind.Length)
        sentence = sentence.Insert(index, replacementWord)
    }
public static string Replace(this string source, string oldString, 
                             string newString, StringComparison comparison)
{
    int index = source.IndexOf(oldString, comparison);

    while (index > -1)
    {
        source = source.Remove(index, oldString.Length);
        source = source.Insert(index, newString);

        index = source.IndexOf(oldString, index + newString.Length, comparison);
    }

    return source;
}
public static string Replace(this string source, string oldString, 
                             string newString, StringComparison comparison,
                             bool recursive = true)
{
    int index = source.IndexOf(oldString, comparison);

    while (index > -1)
    {
        source = source.Remove(index, oldString.Length);
        source = source.Insert(index, newString);

        if (!recursive)
        {
            return source;
        }
        index = source.IndexOf(oldString, index + newString.Length, comparison);
    }

    return source;
}
结果:

巴纳纳纳

如果您仍然希望递归性质是可选的:

代码:

用法:

    string sentence = "We know it contains 'camel' word."; 
    string wordToFind = "camel";
    string replacementWord = "horse";

    int index = sentence.IndexOf(wordToFind , StringComparison.OrdinalIgnoreCase)
    // Did we match the word regardless of case
    bool match = index >= 0;

    // perform the replace on the matched word
    if(match) {
        sentence = sentence.Remove(index, wordToFind.Length)
        sentence = sentence.Insert(index, replacementWord)
    }
public static string Replace(this string source, string oldString, 
                             string newString, StringComparison comparison)
{
    int index = source.IndexOf(oldString, comparison);

    while (index > -1)
    {
        source = source.Remove(index, oldString.Length);
        source = source.Insert(index, newString);

        index = source.IndexOf(oldString, index + newString.Length, comparison);
    }

    return source;
}
public static string Replace(this string source, string oldString, 
                             string newString, StringComparison comparison,
                             bool recursive = true)
{
    int index = source.IndexOf(oldString, comparison);

    while (index > -1)
    {
        source = source.Remove(index, oldString.Length);
        source = source.Insert(index, newString);

        if (!recursive)
        {
            return source;
        }
        index = source.IndexOf(oldString, index + newString.Length, comparison);
    }

    return source;
}
结果:

巴纳纳纳


这里还有另一种选择,它使用StringComparison作为扩展方法。在StringBuilder对象上。我读过一些文章,指出StringBuilder使用内存可能比使用字符串更高效。如果需要的话,您可以很容易地修改它来处理字符串

string source = "banana";
Console.WriteLine(source.Replace("AN", "banana", StringComparison.OrdinalIgnoreCase, false));
//
///查找/替换的扩展方法替换StringBuilder对象中的文本
/// 
///源StringBuilder对象
///要搜索的字符串
///字符串以替换每次发生的旧字符串
///要使用的字符串比较
///原始Stringbuilder及其替换件
公共静态StringBuilder替换(此StringBuilder原件,
字符串oldString、字符串newString、字符串比较StringComparison(字符串比较)
{
//如果有任何内容为空,或者oldString为空,请使用原始值退出
if(newString==null | | original==null | | string.IsNullOrEmpty(oldString))
归还原件;
//转换为字符串并使用
//IndexOf,它允许我们使用StringComparison。
int pos=original.ToString().IndexOf(oldString,0,stringComparison);
//循环直到找到并替换所有匹配项
而(位置>=0)
{
//移除旧字符串并插入新字符串。
原始。删除(pos,oldString.Length)。插入(pos,newString);
//在最后一次替换后,从1个字符开始获取下一个匹配(以避免可能的无限循环)
pos=original.ToString().IndexOf(oldString,pos+newString.Length+1,stringComparison);
}
归还原件;
}

为什么不导入Microsoft.VisualBasic命名空间并使用VB字符串.Replace方法

乙二醇

vbTextCompare强制进行不区分大小写的替换。工作完成了


好吧,它不是“纯”C#,但它能让你以更少的复杂性和混乱到达你想要去的地方。

在库和框架时代,这需要大量的检查和调试性能往往是受害者。这就是堆栈溢出的原因。;)如果我只匹配那个词呢?我需要匹配文本中的一些关键字,并用关键字替换它们(并且仅替换它们),以便使它们变成红色。@Luca-我可能会使用一个自定义的MatchEvaluator来检查匹配的子字符串后面或前面是否有字母或数字,并且仅在不发生这种情况时才返回替换字符串。我将添加一个示例(可能是不完整的,并且经过了最低限度的测试)。@minitech好吧,如果单词边界真的有效,当然,但在他的示例中,他想替换引号中的一个单词。我认为本例中的单词边界是引号字符,而不是第一个“c”。自定义匹配计算器允许使用简化的正则表达式执行任意逻辑。啊。“向后看”可能也有用,但我知道这两种方法都是值得的!您还应该在正则表达式的模式上使用Regex.Escape()。这只会替换
源代码中第一次出现的
oldString
,与此不同