2010-03-30 22 views
10

मुझे स्ट्रिंग से सभी सबस्ट्रिंग प्राप्त करने की आवश्यकता है।
पूर्व के लिए:
दो तारों के बीच सभी सबस्ट्रिंग्स खोजें

StringParser.GetSubstrings("[start]aaaaaa[end] wwwww [start]cccccc[end]", "[start]", "[end]"); 

कि 2 स्ट्रिंग "aaaaaa" और "cccccc" रिटर्न मान लीजिए कि हमें घोंसले का केवल एक स्तर है। regexp के बारे में निश्चित नहीं है, लेकिन मुझे लगता है कि यह उपयोगकर्ता उपयोगी होगा।

+0

1 नेस्टिंग साधन के स्तर '[शुरू] xxx [शुरू] yyy [अंत] zzz [अंत]' संभव है? – kennytm

+0

यह impossibe है। –

+0

यदि आप HTML या XML को पार्स करने के लिए ऐसा कर रहे हैं, तो बेहतर तरीके हैं ... – Randolpho

उत्तर

31
private IEnumerable<string> GetSubStrings(string input, string start, string end) 
{ 
    Regex r = new Regex(Regex.Escape(start) + "(.*?)" + Regex.Escape(end)); 
    MatchCollection matches = r.Matches(input); 
    foreach (Match match in matches) 
     yield return match.Groups[1].Value; 
} 
+0

सटीक मुझे क्या चाहिए, धन्यवाद –

+3

+1 - विशेष रूप से Regex.Escape के लिए :) –

2

बेहतर होगा कि तुम नियम है कि अपने मिलान जरूरतों को नियंत्रित परिभाषित करने की जरूरत जा रहे हैं। किसी भी प्रकार के मिलान या खोज कोड का निर्माण करते समय आपको इस बात के बारे में स्पष्ट होना चाहिए कि आप किस इनपुट का अनुमान लगाते हैं और आपको उत्पादन करने की क्या आवश्यकता है। यदि आप इन प्रश्नों को करीबी विचार में नहीं लेते हैं तो बग्गी कोड का उत्पादन करना बहुत आसान है। उस ने कहा ...

आपको नियमित अभिव्यक्तियों का उपयोग करने में सक्षम होना चाहिए। नेस्टिंग इसे थोड़ा अधिक जटिल बना सकता है लेकिन फिर भी करने योग्य (आप नेस्टेड परिदृश्यों में मिलान करने की अपेक्षा करने के आधार पर)। आपको कुछ शुरू करना चाहिए:

var start = "[start]"; 
var end = "[end]"; 
var regEx = new Regex(String.Format("{0}(.*){1}", Regex.Escape(start), Regex.Escape(end))); 
var source = "[start]aaaaaa[end] wwwww [start]cccccc[end]"; 
var matches = regEx.Match(source); 

उपरोक्त कोड को आपकी आवश्यकताओं के लिए उपयुक्त फ़ंक्शन में लपेटना छोटा होना चाहिए।

2

आप रेगुलर एक्सप्रेशन का उपयोग, लेकिन अपने तर्कों पर Regex.Escape कॉल करने के लिए याद कर सकते हैं:

public static IEnumerable<string> GetSubStrings(
    string text, 
    string start, 
    string end) 
{ 
    string regex = string.Format("{0}(.*?){1}", 
     Regex.Escape(start), 
     Regex.Escape(end)); 

    return Regex.Matches(text, regex, RegexOptions.Singleline) 
     .Cast<Match>() 
     .Select(match => match.Groups[1].Value); 
} 

इतना है कि यह भले ही अपने पाठ में नए-लाइनें हैं से मेल खाएगी मैं भी SingleLine विकल्प जोड़ा।

4

यहां एक समाधान है जो नियमित अभिव्यक्तियों का उपयोग नहीं करता है और घोंसले को ध्यान में रखता नहीं है।

public static IEnumerable<string> EnclosedStrings(
    this string s, 
    string begin, 
    string end) 
{ 
    int beginPos = s.IndexOf(begin, 0); 
    while (beginPos >= 0) 
    { 
     int start = beginPos + begin.Length; 
     int stop = s.IndexOf(end, start); 
     if (stop < 0) 
      yield break; 
     yield return s.Substring(start, stop - start); 
     beginPos = s.IndexOf(begin, stop+end.Length); 
    }   
} 
0

मैं ऊब गया था, और इस तरह मैं एक बेकार सूक्ष्म बेंचमार्क जो "साबित होता है" (मेरी डाटासेट है, जो अक्षरों के 7K अप करने के लिए तार और प्रारंभ/समाप्ति मापदंडों के लिए <b> टैग नहीं है पर) कि juharr मेरी संदेह बना का समाधान कुल मिलाकर तीन में से सबसे तेज़ है।

परिणाम (1000000 पुनरावृत्तियों * 20 परीक्षण मामलों):

juharr: 6371ms 
Jake: 6825ms 
Mark Byers: 82063ms 

नोट: संकलित regex बातें मेरी डाटासेट पर ज्यादा गति नहीं किया।

0

Regex मुक्त विधि:

public static List<string> extract_strings(string src, string start, string end) 
{ 
    if (src.IndexOf(start) > 0) 
    { 
     src = src.Substring(src.IndexOf(start)); 
    } 
    string[] array1 = src.Split(new[] { start }, StringSplitOptions.None); 
    List<string> list = new List<string>(); 
    foreach (string value in array1) 
    { 
     if (value.Contains(end)) 
     { 
      list.Add(value.Split(new[] { end }, StringSplitOptions.None)[0]); 
     } 
    } 
    return list; 
} 
संबंधित मुद्दे