2010-03-30 31 views
10

Tôi cần lấy tất cả các chất nền từ dây.
Đối với ví dụ:
Tìm tất cả các chất nền giữa hai dây

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

trả về 2 chuỗi "aaaaaa" và "cccccc" Giả sử chúng ta chỉ có một mức độ làm tổ. Không chắc chắn về regexp, nhưng tôi nghĩ rằng nó sẽ có ích.

+0

1 mức độ phương tiện làm tổ '[bắt đầu] xxx [bắt đầu] yyy [cuối] zzz [cuối]' là có thể? – kennytm

+0

Đó là impossibe. –

+0

Nếu bạn làm điều này để phân tích cú pháp HTML hoặc XML, có những cách tốt hơn ... – Randolpho

Trả lời

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

Chính xác những gì tôi cần, cảm ơn –

+3

+1 - đặc biệt là đối với Regex.Escape :) –

2

Bạn sẽ cần xác định rõ hơn các quy tắc chi phối nhu cầu phù hợp của mình. Khi xây dựng bất kỳ loại mã kết hợp hoặc tìm kiếm nào bạn cần phải thay đổi rõ ràng về những yếu tố đầu vào bạn dự đoán và kết quả đầu ra nào bạn cần để sản xuất. Rất dễ dàng để tạo mã lỗi nếu bạn không xem xét những câu hỏi này. Điều đó nói rằng ...

Bạn sẽ có thể sử dụng cụm từ thông dụng. Làm tổ có thể làm cho nó phức tạp hơn một chút nhưng vẫn có thể thực hiện được (tùy thuộc vào những gì bạn mong đợi để phù hợp trong các kịch bản lồng nhau). Một cái gì đó như thế sẽ giúp bạn bắt đầu:

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

Sẽ không quan trọng để bao bọc mã ở trên thành một chức năng phù hợp với nhu cầu của bạn.

2

Bạn có thể sử dụng một biểu thức chính quy, nhưng hãy nhớ để gọi Regex.Escape trên lập luận của bạn:

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

Tôi cũng đã thêm tùy chọn SingleLine để nó sẽ phù hợp ngay cả khi có mới dòng trong văn bản của bạn.

4

Đây là giải pháp không sử dụng cụm từ thông dụng và không tính đến việc lồng ghép.

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

tôi đã chán, và do đó tôi đã chuẩn vi vô ích mà "chứng minh" (trên bộ dữ liệu của tôi, trong đó có chuỗi lên đến 7k của nhân vật và <b> thẻ cho các thông số bắt đầu/kết thúc) nghi ngờ của tôi rằng juharr Giải pháp của là giải pháp nhanh nhất trong ba giải pháp tổng thể.

Kết quả (1000000 lặp * trường hợp 20 thử nghiệm):

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

LƯU Ý: Biên soạn regex không điều tốc độ lên nhiều vào dữ liệu của tôi.

0

Regex-miễn phí phương pháp:

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; 
} 
Các vấn đề liên quan