2012-06-15 41 views
7

Tôi có một loạt các giá trị được nhóm theo một định dạng cụ thể và muốn sử dụng một biểu thức duy nhất để chụp chúng thành các nhóm. Ví dụ, tôi có -group1 -group2 -group3 và đang cố gắng sử dụng một cái gì đó tương tự như (-[\s\S]{1,}?) Điều này về cơ bản cho phép tôi nắm bắt toàn bộ chuỗi thành một nhóm nhưng tôi muốn có thể trả về từng giá trị riêng biệt. Tôi đã tìm ra ? sẽ buộc nó không tham lam và do đó, chia mẫu phù hợp thành ba nhóm riêng biệt (ví dụ). Hiện tại, tôi chỉ đơn giản lặp lại tham chiếu (-[\s\S]*?) nhưng có vẻ như cần có một biểu thức thanh lịch hơn.
Cảm ơn!Biểu thức chính quy để chọn các nhóm lặp

+0

Điều này hơi mơ hồ. Bạn có thể hiển thị một số văn bản mẫu và kết quả nhóm dự kiến, bao gồm cả những gì bạn dự định trả về không? –

+0

Nhân tiện, '[\ s \ S]' nói "Phù hợp với bất kỳ dấu cách hoặc ký tự không dấu cách nào". Nghĩ về điều đó. ;) – qJake

Trả lời

14

Bạn là người may mắn vì C# là một trong số ít những ngôn ngữ (nếu không phải là người duy nhất) có hỗ trợ subexpression chụp

https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.capture(v=vs.110)

API .NET có thể được xem như sau

Matches 
    Groups (most regex engines stop here) 
     Captures (unique for .NET) 

Nó không rõ ràng từ câu hỏi của bạn những gì bạn muốn kết hợp chính xác nhưng điều này sẽ giúp bạn bắt đầu. Hỏi lại nếu bạn bị mắc kẹt.

string input = "-group1 -group2 "; 
    string pattern = @"(-\S*\W){2}"; 
    foreach (Match match in Regex.Matches(input, pattern)) 
    { 
    Console.WriteLine("Match: {0}", match.Value); 
    for (int groupCtr = 0; groupCtr < match.Groups.Count; groupCtr++) 
    { 
     Group group = match.Groups[groupCtr]; 
     Console.WriteLine(" Group {0}: {1}", groupCtr, group.Value); 
     for (int captureCtr = 0; captureCtr < group.Captures.Count; captureCtr++) 
      Console.WriteLine("  Capture {0}: {1}", captureCtr, 
          group.Captures[captureCtr].Value); 
    }      
    } 

này ouputs

Match: -group1 -group2 
    Group 0: -group1 -group2 
     Capture 0: -group1 -group2 
    Group 1: -group2 
     Capture 0: -group1 
     Capture 1: -group2 

Như bạn có thể nhìn thấy (Nhóm 1, Chụp 0) và (Nhóm 1, Chụp 1) cung cấp ảnh chụp cá nhân của một nhóm (và không phải là cuối cùng như trong hầu hết các ngôn ngữ)

địa chỉ này tôi nghĩ về những gì bạn mô tả là "để có thể backreference mỗi giá trị riêng"

(bạn sử dụng backreference hạn nhưng tôi không nghĩ rằng bạn đang hướng tới ar mẫu eplacement phải không?)

+1

+1. Tôi tin rằng đây là những gì ông đã yêu cầu là tốt. Ngoài ra, PHP cung cấp điều này với '' preg_match_all (...) '' hàm; sử dụng cờ '' PREG_SET_ORDER'', nó trả về mảng đa chiều, mảng đầu tiên chứa tập đầu tiên, mảng thứ hai chứa tập thứ hai, v.v. (Các cờ khác cho phép biểu diễn khác nhau.) Đoán của tôi là nếu .NET. và PHP đã thực hiện nó, các ngôn ngữ khác cũng vậy. –

+0

@ acheong87 Bình luận tốt, tôi sẽ thêm nó vào câu trả lời để không xúc phạm các ngôn ngữ khác :) Tôi có nó từ chuyên gia regexp Jan Goyvaerts rằng .NET là duy nhất trên khía cạnh này nhưng tôi không hoạt động đủ trên các nền tảng khác để quay lại lên. – buckley

+2

@ acheong87, đó không phải là điều tương tự. 'preg_match_all()' áp dụng regex nhiều lần và trả về kết quả thu được, tương tự như phương thức 'Matches()' của .NET. OP muốn thực hiện * một * trận đấu sẽ tiêu thụ toàn bộ chuỗi, sau đó chia nhỏ các ảnh chụp cá nhân. .NET cung cấp 'CaptureCollection' cho mục đích đó, nhưng PHP không có tương đương. –

0

Hãy thử điều này:

(-.+?)(\s|$) 

nhóm chụp đầu tiên của bạn sẽ có những gì bạn muốn (-group1, -group2, vv).

Nếu bạn muốn kiểm soát nhiều hơn những gì để cho phép sau khi -, thay đổi .+?, ví dụ, [a-zA-Z0-9]+? để chỉ phù hợp với ký tự chữ.

2

Với .NET regex (và gần như chỉ NET), bạn có thể sử dụng:

(?:(-\S+)\s*)+ 

Nhóm 1 sẽ chứa một danh sách của tất cả các chuỗi con phù hợp.

Hoặc có thể chỉ sử dụng Matches là đủ trong trường hợp của bạn:

var re = new Regex(@"-\S+"); 
var matches = re.Matches(str); 
Các vấn đề liên quan