2011-05-17 21 views
34
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"; 

कैसे में मामले की अनदेखी करने के लिए छोड़ दिया स्ट्रिंग पर ignoreCase का समर्थन नहीं करता string.Replace के बावजूद 'घोड़ा' के साथ वाक्य में 'ऊंट' को बदलने के लिए?कैसे String.replace

+0

संभावित डुप्लिकेट [क्या स्ट्रिंग का कोई विकल्प है। बदलें जो केस असंवेदनशील है?] (Https://stackoverflow.com/questions/244531/is-there-an-alternative-to-string-replace-that -इस-केस-असंवेदनशील) –

उत्तर

47

एक रेगुलर एक्सप्रेशन का उपयोग करें:

var regex = new Regex("camel", RegexOptions.IgnoreCase); 
var newSentence = regex.Replace(sentence, "horse"); 

बेशक, यह भी मिलान कर देंगे शब्द ऊंट युक्त है, लेकिन यह स्पष्ट नहीं है अगर आपको लगता है कि या नहीं चाहते।

यदि आपको सटीक मिलान की आवश्यकता है तो आप कस्टम MatchEvaluator का उपयोग कर सकते हैं।

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 sentence in sentences) 
{ 
    var evaluator = new MatchEvaluator(match => Evaluators.Wrap(match, sentence, "<span class='red'>{0}</span>")); 
    Console.WriteLine(regex.Replace(sentence, evaluator)); 
} 
+0

क्या होगा यदि मैं केवल उस विशेष शब्द से मेल खाता हूं? मुझे लाल रंग में बनाने के लिए टेक्स्ट के भीतर कुछ कीवर्ड मिलान करना होगा और कीवर्ड के साथ थम्स (और बस उन्हें) को प्रतिस्थापित करना होगा। – Francesco

+0

@ लुका - मैं शायद एक कस्टम MatchEvaluator का उपयोग करता हूं जो यह देखने के लिए जांच करता है कि मिलान किए गए सबस्ट्रिंग के पास या उसके बाद एक अक्षर या अंक है या नहीं, और जब ऐसा नहीं होता है तो केवल प्रतिस्थापन स्ट्रिंग देता है। मैं एक नमूना जोड़ूंगा (अपूर्ण, शायद, और न्यूनतम परीक्षण)। – tvanfosson

+0

'\ b' का उपयोग क्यों नहीं करें? – Ryan

2

तुम भी इस्तेमाल कर सकते हैं String.IndexOf

http://msdn.microsoft.com/en-us/library/system.string.indexof.aspx

आप थोड़ा बेहतर प्रदर्शन प्राप्त कर सकते हैं RegExpressions के साथ इस तरह से ऐसा करना (मैं उन्हें घृणा करता हूं क्योंकि वे सहज नहीं हैं और स्क्रू करने में आसान हैं, हालांकि यह सरल .Net फ़ंक्शन कॉल एक सार तत्व बनाता है ctual गन्दा RegEx, और त्रुटि के लिए ज्यादा जगह प्रदान नहीं करता है), लेकिन यह शायद आपके लिए चिंता नहीं है; कंप्यूटर वास्तव में इन दिनों वास्तव में तेजी से हैं, है ना? :) इंडेक्सऑफ के लिए ओवरलोड जो स्ट्रिंग कॉम्परिसन ऑब्जेक्ट लेता है, आपको वैकल्पिक रूप से केस को अनदेखा करने की अनुमति देता है, और क्योंकि इंडेक्सऑफ किसी निर्दिष्ट स्थिति से पहली घटना देता है, तो आपको एक स्ट्रिंग को कई घटनाओं को संसाधित करने के लिए कोड करना होगा।

+0

पुस्तकालयों और ढांचे के युग में बहुत सारे चेक और डीबग की ज़रूरत है, जो ज्यादातर बार शिकार होता है। – Xaqron

+0

स्टैक ओवरफ़्लो यही है। ;) – Shavais

3

वजह से Utiltize StringComparison अपने काम OrdinalIgnoreCase

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

ज़रूर अच्छा होगा सी # स्ट्रिंग वर्ग एक ignoreCase() विधि जावा की तरह था।

14

स्ट्रिंग चाल करने के लिए एक विस्तार विधि जोड़ें:

उपयोग:

string yourString = "TEXTTOREPLACE"; 
yourString.Replace("texttoreplace", "Look, I Got Replaced!", StringComparison.OrdinalIgnoreCase); 

कोड:

using System; 
using System.Collections.Generic; 
using System.IO; 

public static class Extensions 
{ 
    public static string Replace(this string source, string oldString, string newString, StringComparison comp) 
    { 
     int index = source.IndexOf(oldString, comp); 

     // Determine if we found a match 
     bool MatchFound = index >= 0; 

     if (MatchFound) 
     { 
      // Remove the old text 
      source = source.Remove(index, oldString.Length); 

      // Add the replacemenet text 
      source = source.Insert(index, newString);    
     } 

     return source; 
    } 
} 
+5

यह 'स्रोत' के भीतर 'पुरानी स्ट्रिंग' की पहली घटना को प्रतिस्थापित करता है, मूल 'प्रतिस्थापन' – bdukes

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

इसके बारे में कुछ के रूप में के रूप में कुशल नहीं हो सकता है अन्य उत्तरों, लेकिन मैं sntbob द्वारा लिखित कस्टमरिप्लेस फ़ंक्शन की तरह हूं।

हालांकि, इसमें कोई दोष है। यदि टेक्स्ट प्रतिस्थापन रिकर्सिव है तो यह अनंत लूप का कारण बन जाएगा। उदाहरण के लिए, कस्टम रीप्लेस ("मैं केले खाते हैं!", "ए", "केले", झूठी, झूठी) एक अनंत लूप का कारण बनती है और स्ट्रिंग बड़ी बढ़ती रहती है। उदाहरण के लिए, चौथे पुनरावृत्ति के बाद स्ट्रिंग "मैं bbbbbananaanaanaanaanas खाते हैं!"

यदि आप केवल "केले" के अंदर "ए" के दो उदाहरणों को प्रतिस्थापित करना चाहते हैं तो आपको एक और दृष्टिकोण लेना होगा। मैंने इस मामले के लिए स्नैटबोब कोड को संशोधित किया। मैं मानता हूं कि यह बहुत अधिक गड़बड़ है, लेकिन यह रिकर्सिव प्रतिस्थापन को संभालता है।

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

यहाँ एक StringComparison लेने एक विस्तार विधि, string.IndexOf का उपयोग कर रहा है:

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

Btw, यहाँ भी है एक समान होता है-विधि भी एक StringComparison लेने:

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

कुछ परीक्षण :

[TestFixture] 
public class ExternalTests 
{ 
    private static string[] TestReplace_args = 
     { 
      "ab/B/c/ac", 
      "HELLO World/Hello/Goodbye/Goodbye World", 
      "Hello World/world/there!/Hello there!", 
      "hello WoRlD/world/there!/hello there!", 
      "///", 
      "ab///ab", 
      "/ab/cd/", 
      "a|b|c|d|e|f/|//abcdef", 
      "a|b|c|d|e|f|/|/:/a:b:c:d:e:f:", 
     }; 

    [Test, TestCaseSource("TestReplace_args")] 
    public void TestReplace(string teststring) 
    { 
     var split = teststring.Split("/"); 
     var source = split[0]; 
     var oldValue = split[1]; 
     var newValue = split[2]; 
     var result = split[3]; 
     Assert.That(source.Replace(oldValue, newValue, StringComparison.OrdinalIgnoreCase), Is.EqualTo(result)); 
    } 
} 
4

यहां मेरी विस्तार विधि है, जो sntbob's की पुनरावृत्ति के साथ Tom Beech's को जोड़ती है, और ksun ने बग को क्लीनर फ़िक्स किया है।

कोड:

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

उपयोग:

string source = "banana"; 
Console.WriteLine(source.Replace("AN", "banana", StringComparison.OrdinalIgnoreCase)); 

परिणाम:

bbananabananaa

और, यदि आप अभी भी पुनरावर्ती प्रकृति चाहते हैं, तो सेशन होने के लिए राष्ट्रीय:

कोड:

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 source = "banana"; 
Console.WriteLine(source.Replace("AN", "banana", StringComparison.OrdinalIgnoreCase, false)); 

परिणाम:

bbananaana

0

यहाँ एक और विकल्प StringComparison डब्ल्यू का उपयोग करता है है एक विस्तार विधि के साथ।

public static StringBuilder Replace(this StringBuilder original, 
        string oldString, string newString, StringComparison stringComparison) 
    { 
     if (newString == null || original == null || string.IsNullOrEmpty(oldString)) 
      return original; 

     int pos = original.ToString().IndexOf(oldString, 0, stringComparison); 
     while (pos >= 0) 
     { 
      original.Remove(pos, oldString.Length).Insert(pos, newString); 

      pos = original.ToString().IndexOf(oldString, pos + newString.Length + 1, stringComparison); 
     } 
     return original; 
    } 
+0

के विपरीत, क्या आप इसे अधिक समझने योग्य बनाने के लिए टिप्पणियां जोड़ सकते हैं? – Sandeep

1

क्यों न सिर्फ Microsoft.VisualBasic नाम स्थान आयात और वीबी Strings.Replace विधि का उपयोग करें?

https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.strings.replace(v=vs.110).aspx

जैसे

var newString = Strings.Replace(SourceString, FindTextValue, ReplacementTextValue, 1, -1, Constants.vbTextCompare); 

vbTextCompare एक केस-संवेदी प्रतिस्थापन बाध्य करती है। काम हो गया।

ठीक है, यह 'शुद्ध' सी # नहीं है, लेकिन यह आपको उस स्थान पर ले जाता है जहां आप बहुत कम जटिलता और गड़बड़ी के साथ जाना चाहते हैं।