2010-08-20 26 views
5

Trong .NET, regex không tổ chức chụp như tôi mong đợi. (Tôi sẽ không gọi đây là một lỗi, bởi vì rõ ràng là ai đó dự định nó. Tuy nhiên, đó không phải là cách tôi mong đợi nó hoạt động cũng như tôi thấy nó hữu ích.).NET regex không theo thứ tự mong đợi

Regex này là dành cho thành phần công thức (đơn giản hóa vì lợi ích ví dụ):

(?<measurement>   # begin group 
    \s*      # optional beginning space or group separator 
    (
    (?<integer>\d+)|  # integer 
    (
     (?<numtor>\d+)  # numerator 
    /
     (?<dentor>[1-9]\d*) # denominator. 0 not allowed 
    ) 
) 
    \s(?<unit>[a-zA-Z]+) 
)+      # end group. can have multiple 

chuỗi của tôi: 3 tbsp 1/2 tsp

nhóm Kết quả và chụp:

[đo lường] [0] = 3 muỗng canh
[đo lường] [] = 1/2 tsp
[nguyên] [0] = 3
[numtor] [] = 1
[dentor] [] = 2
[đơn vị] [0] = tbsp
[đơn vị] [] = tsp

Thông báo như thế nào mặc dù 1/2 tsp là trong Capture 2, đó là bộ phận trong [0] vì những đốm là previousl y không sử dụng.

Có cách nào để đưa tất cả các phần có chỉ mục hữu ích dự đoán được mà không cần phải chạy lại từng nhóm thông qua regex một lần nữa?

Trả lời

1

Có cách nào để có được tất cả các phần để có các chỉ mục hữu ích dự đoán được mà không cần phải chạy lại từng nhóm thông qua regex một lần nữa?

Không có ảnh chụp.Và nếu bạn đang đi để thực hiện nhiều trận đấu dù sao, tôi khuyên bạn nên xóa + và phù hợp với từng thành phần của phép đo riêng biệt, như vậy:

string s = @"3 tbsp 1/2 tsp"; 

    Regex r = new Regex(@"\G\s* # anchor to end of previous match 
    (?<measurement>   # begin group 
     (
     (?<integer>\d+)  # integer 
     | 
     (
      (?<numtor>\d+)  # numerator 
     /
      (?<dentor>[1-9]\d*) # denominator. 0 not allowed 
     ) 
    ) 
     \s+(?<unit>[a-zA-Z]+) 
    )       # end group. 
    ", RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture); 

    foreach (Match m in r.Matches(s)) 
    { 
    for (int i = 1; i < m.Groups.Count; i++) 
    { 
     Group g = m.Groups[i]; 
     if (g.Success) 
     { 
     Console.WriteLine("[{0}] = {1}", r.GroupNameFromNumber(i), g.Value); 
     } 
    } 
    Console.WriteLine(""); 
    } 

đầu ra:

[measurement] = 3 tbsp 
[integer] = 3 
[unit] = tbsp 

[measurement] = 1/2 tsp 
[numtor] = 1 
[dentor] = 2 
[unit] = tsp 

Các \G tại bắt đầu đảm bảo rằng các trận đấu chỉ xảy ra tại điểm mà trận đấu trước đó đã kết thúc (hoặc ở đầu của đầu vào nếu đây là trận đấu đầu tiên). Bạn cũng có thể lưu vị trí kết thúc trận đấu giữa các cuộc gọi, sau đó sử dụng phương thức hai đối số Matches để tiếp tục phân tích cú pháp tại cùng một điểm đó (như thể đó thực sự là đầu của đầu vào).

1

Có vẻ như bạn có thể cần phải lặp qua đầu vào, phù hợp với một phép đo tại một thời điểm. Sau đó, bạn sẽ có quyền truy cập dự đoán được vào các phần của phép đo đó, trong vòng lặp lặp lại cho phép đo đó.

-1

Có một cái nhìn lúc này .... đây là một vài ý kiến ​​cho rằng có thể giúp cải thiện regexp

(?<measurement>   # begin group 
    \s*      # optional beginning space or group separator 
    (
    (?<integer>\d+)\.?| # integer 
    (
     (?<numtor>\d+)  # numerator 
    /
     (?<dentor>[1-9]\d*) # denominator. 0 not allowed 
    ) 
) 
    \s(?<unit>[a-zA-Z]+) 
)+      # end group. can have multiple 
  • Các regex đang mong đợi một không gian lúc bắt đầu .... sau thẻ đo lường ....
  • (?<integer>\d+) tôi sẽ cố gắng \s? thay vì \. để nắm bắt những khoảng trắng vì đó là thoát khỏi toàn dừng lại và sẽ mong đợi một full-stop để xuất hiện ở đâu đó ..
  • thoát khỏi/như thế này để làm nó như một lite ral \/
  • Có gì | tách cho? đó là làm hai phần riêng lẫn nhau - hoặc là một 'nguyên' hoặc 'numtor' với một 'dentor' ... phần trông bối rối ...
+0

'/' không có ý nghĩa đặc biệt trong các regex. Một số hương vị sử dụng nó như một dấu phân cách cho các chữ * regex * (ví dụ như JavaScript), nhưng trong .NET nó chỉ là một ký tự khác; bạn không cần phải thoát khỏi nó. –

+0

Cảm ơn bạn đã dành thời gian trả lời, nhưng tôi không cần phân tích regex - chỉ ở đây để hiển thị vấn đề được đề cập. – Dinah

Các vấn đề liên quan