2010-03-30 9 views
10

문자열에서 모든 하위 문자열을 가져와야합니다. 예를 들어
:
2 문자열 "AAAAAA"와 "CCCCCC"를 반환두 문자열 사이의 모든 하위 문자열 찾기

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

우리가 중첩의 한 수준이 가정하자. regexp에 대해서는 잘 모르겠지만 사용자 중심으로 생각됩니다.

+0

'1 레벨 XXX YYY [END] ZZZ [END]을 [START] '있다 [START]는? – kennytm

+0

그것은 불가능합니다. –

+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

나는 지루했다, 그래서 나는 juharr 것을 (문자 7K까지 문자열과 시작/종료 매개 변수에 대한 <b> 태그가 내 데이터 세트에) 내 의심을 "증명"쓸모없는 마이크로 벤치 마크를 만들어의 솔루션은 전체 세 가지 중에서 가장 빠릅니다.

결과 (1000000 반복 * 20 테스트 케이스) :

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

참고 : 컴파일 된 정규식 내 데이터 세트에 대한 많은 것들을 최대 속도를하지 않았다.

0

정규식없는 방법 중첩 수단

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