2011-03-08 46 views
9

Tôi đã có một regex khá dài để khớp với mục nhập trong danh sách mà tôi đang xử lý. Danh sách phải là một hoặc nhiều mục nhập, được phân cách bằng dấu phẩy. Xem xét một regex:Lặp lại được phân tách bằng dấu phẩy

([abc]+|[123]+) 

để nhập. Để phù hợp với danh sách bằng dấu phẩy của tôi, tôi phù hợp chống lại một cái gì đó như thế này:

([abc]+|[123]+)(,([abc]+|[123]+))* 

(Có vẻ đặc biệt là ngu ngốc với regex khó chịu của tôi thay vì con đường ngắn tôi sử dụng ở đây cho ví dụ)

tôi cảm thấy phải có cách tốt hơn là có hai bản sao của mục nhập - một lần cho mục nhập đầu tiên, một lần nữa cho và theo cặp dấu phẩy/nhập.

Trả lời

3

Cái gì đó như có lẽ đây:

((?!=^|,)([abc123]))+ 

Broke xuống đó là:

(      # start of parent capture 
    (?!=^|,)    # look ahead and find either the start of a line or a comma 
    ([abc123])    # actual pattern to look for (token) 
)+      # say this whole pattern is repeatable 

PHP Demo (Đã đơn giản nhất cách để chứng minh)

+0

Tôi không nghĩ bạn muốn '!' Nhìn về phía trước (cái nhìn tiêu cực), nhưng nhìn về phía trước không thực sự khớp với ký tự, vì vậy điều này sẽ không khớp. Bạn nên ổn mà không có lookahead '(?: (?:^|,) ([A-c1-3])) +' – jswolf19

+0

@ jswolf19: Tôi sử dụng nó để tránh nhân vật cuộn tròn trong trận đấu. Tôi đoán sở thích cá nhân. - sự kết hợp cũng mang lại cho tôi cả trận đấu đầu tiên và phần còn lại. (nếu không có nó, tôi sẽ chỉ nhận được mã thông báo đầu tiên hoặc số 2 trở đi) –

+0

Tôi biết bạn không muốn ',' trong trận đấu, nhưng nó phải khớp với nhau: nếu bạn có 'a, 1', sau đó regex của bạn sẽ không phù hợp với nó. lookahead nhìn thấy ',', nhưng nó vẫn còn đó khi bạn cố gắng để phù hợp với 1 bởi vì lookahead không ném ',' đi. Bạn cần một nhóm không bắt giữ cho '(?:)' Đó. – jswolf19

6

Hình như bạn muốn backreferences.

([abc123])(,\1)* 

Ngoài ra, chỉ FYI, [abc]|[123] tương đương với [abc123].


Edit: Dựa trên chỉnh sửa của bạn, tôi nghĩ là tôi hiểu lầm những gì bạn đang cố gắng để làm. Hãy thử điều này:

([abc123]+(,|$))* 

Hoặc nếu bạn muốn trở thành ít hạn chế:

([^,]+(,|$))* 

này phù hợp với các xâu kí tự không dấu phẩy phân cách bằng dấu phẩy. Một cách tiếp cận đơn giản hơn sẽ chỉ là một kết hợp toàn cầu cho chính mình là [^,]+. Trong JavaScript, mà sẽ trông như thế này:

myString.match(/[^,]+/g) //or /[abc123]+/g, or whatever 

Hoặc bạn chỉ có thể chia rẽ về dấu phẩy:

myString.split(/,/) 
+0

có nghĩa là mã thông báo tiếp theo phải giống với mã thông báo trước, không phải mã thông báo phải phù hợp với mẫu. (không chắc đó là những gì OP muốn, họ chỉ tò mò nếu họ cần phải xác định các mô hình hai lần [tôi có thể sai ...]) –

+0

@ Brad: Đó không phải là những gì anh ta sẽ làm? Có lẽ tôi đang bối rối. –

+0

@JustinEMorgan: Có thể bạn đã đúng. Tôi đọc nó như là "tôi có cần phải xác định các mô hình để tìm hai lần?", Và "nếu không, làm thế nào để tôi tránh làm như vậy". –

0

Trong trường hợp của tôi, tôi đang thử nghiệm toàn bộ dòng.

/(?!^,)^((^|,)([abc]+|[123]+))+$/.test('a,b,c,1,2,3'); 
true 

Dấu chú âm phủ định không bao gồm dấu phẩy ban đầu.

/(?!^,)^((^|,)([abc]+|[123]+))+$/.test(',a,b,c,1,2,3'); 
false 

Nếu bạn cần các thành phần riêng lẻ thực hiện phân tách đơn giản sau khi xác thực.

Tôi đang xác thực các phần và phần phụ thuộc PLSS.

// Check for one or more Section Specs consisting of an optional 
// subsection followed by an "S" and one or two digits. Multiple 
// Section Specs are separated by space or a comma and optional space. 
// 
// Example: SW/4 SW/4 S1, E/2 S2, N/2 N/2 S12 
// 
// Valid subsections are - 
// (1) [NS][EW]/4\s+[NS][EW]/4 eg. NW/4 SE/4 (40 ac) 
// (2) [NSEW]/2\s+[NS][EW]/4  eg. N/2 SE/4 (80 ac) 
// (3) [NS]/2\s+[NS]/2   eg. N/2 S/2 (160 ac) 
// (4) [EW]/2\s+[EW]/2   eg. E/2 W/2 (160 ac) 
// (5) [NS][EW]/4    eg. NE/4 (160 ac) 
// (6) [NSEW]/2     eg. E/2 (320 ac) 
// (7) 1/1      Shorthand for the full section (640 ac) 
// 
// Expressions like E/2 N/2 are not valid. Use NE/4 instead. 
// Expressions like NW/4 E/2 are not valid. You probably want W/2 NE/4. 

var pat = '' + 
    '(([NS][EW]/4|[NSEW]/2)\\s+)?[NS][EW]/4\\s+' + // (1), (2) & (5) 
    '|([NS]/2\\s+)?[NS]/2\\s+' +      // (3) & part of (6) 
    '|([EW]/2\\s+)?[EW]/2\\s+' +      // (4) & part of (6) 
    '|1/1\\s+';          // (7) 

pat = '(' + pat + ')?' + 'S\\d{1,2}';     // a Section Spec 

// Line anchors, join alternatives and negative lookahead to exclude an initial comma 
pat = '(?!^,)^((^|,\\s*|\\s+)(' + pat + '))+$'; 

var re = new RegExp(pat, 'i'); 

console.log(pat); 
(?!^,)^((^|,\s*|\s+)(((([NS][EW]/4|[NSEW]/2)\s+)?[NS][EW]/4\s+|([NS]/2\s+)?[NS]/2\s+|([EW]/2\s+)?[EW]/2\s+|1/1\s+)?S\d{1,2}))+$ 

Sau khi xác thực tôi chia sẻ bằng cách sử dụng một cái nhìn tích cực.

var secs = val.split(/(?<=S\d+)(,\s*|\s+)/i); 
Các vấn đề liên quan