2009-12-31 17 views
12

Khi tôi viết một biểu thức chính quy như:Làm thế nào để tìm thấy các chỉ mục của các nhóm trong các biểu thức chính quy JavaScript phù hợp?

var m = /(s+).*?(l)[^l]*?(o+)/.exec("this is hello to you"); 
console.log(m); 

tôi nhận được một đối tượng phù hợp có chứa những điều sau đây:

{ 
    0: "s is hello", 
    1: "s", 
    2: "l", 
    3: "o", 
    index: 3, 
    input: "this is hello to you" 
} 

Tôi biết chỉ số của toàn bộ trận đấu từ index bất động sản, nhưng tôi cũng cần để biết bắt đầu và kết thúc của các nhóm phù hợp. Sử dụng tìm kiếm đơn giản sẽ không hoạt động. Trong ví dụ này, nó sẽ tìm thấy chữ 'l' đầu tiên thay vì chữ cái l được tìm thấy trong nhóm.

Có cách nào để nhận bù đắp của một nhóm phù hợp không?

+0

Có thể trùng lặp [Nhận chỉ mục của từng lần chụp trong một regex JavaScript] (http://stackoverflow.com/questions/15934353/get-index-of-each-capture-in-a-javascript-regex) – Vanuan

Trả lời

13

Bạn không thể trực tiếp nhận chỉ mục của nhóm đối sánh. Những gì bạn phải làm là lần đầu tiên đưa mỗi nhân vật trong một nhóm phù hợp, thậm chí là những người bạn không quan tâm đến:

var m= /(s+)(.*?)(l)([^l]*?)(o+)/.exec('this is hello to you'); 

Bây giờ bạn đã có toàn bộ trận đấu ở các bộ phận:

['s is hello', 's', ' is hel', 'l', '', 'o'] 

Vì vậy, bạn có thể thêm lên độ dài của chuỗi trước khi nhóm của bạn để có được sự bù đắp từ các chỉ số phù hợp để chỉ số nhóm:

function indexOfGroup(match, n) { 
    var ix= match.index; 
    for (var i= 1; i<n; i++) 
     ix+= match[i].length; 
    return ix; 
} 

console.log(indexOfGroup(m, 3)); // 11 
+0

Đẹp dung dịch. Nhưng trong trường hợp của tôi, tôi cần phải tự động bổ sung thêm parens. Và sửa chữa backreferences nếu có + nhớ số nhóm ban đầu. Nó là cho một highlighter cú pháp với phạm vi phù hợp, và giải pháp hiện tại là sử dụng highlighter halfdone để phân tích cú pháp regexp + làm tất cả các loại công cụ cho cây cú pháp trừu tượng sau đó. Tôi chắc chắn sẽ yêu một giải pháp đơn giản hơn là kết hợp 300 dòng mã. –

+0

Nó yêu cầu sửa đổi regexps oryginal – pie6k

8

tôi đã viết một đơn giản (tốt khởi có một chút cồng kềnh) javascript đối tượng để giải quyết điều này vấn đề về một dự án tôi đã làm việc gần đây. Nó hoạt động giống như câu trả lời được chấp nhận nhưng tạo ra regexp mới và lấy ra dữ liệu bạn yêu cầu tự động.

var exp = new MultiRegExp(/(firstBit\w+)this text is ignored(optionalBit)?/i); 
var value = exp.exec("firstbitWithMorethis text is ignored"); 

value = {0: {index: 0, text: 'firstbitWithMore'}, 
     1: null}; 

Git Repo: My MultiRegExp. Hy vọng điều này sẽ giúp ai đó ra khỏi đó.

chỉnh sửa tháng 8 năm 2015:

Hãy thử tôi: MultiRegExp Live.

1

Một lớp javascript mà cũng có thể phân tích các nhóm lồng nhau được phát hành theo: https://github.com/valorize/MultiRegExp2

Cách sử dụng:

let regex = /a(?:)bc(def(ghi)xyz)/g; 
let regex2 = new MultiRegExp2(regex); 

let matches = regex2.execForAllGroups('ababa bcdefghixyzXXXX')); 

Will output: 
[ { match: 'defghixyz', start: 8, end: 17 }, 
    { match: 'ghi', start: 11, end: 14 } ] 
+0

Có vẻ tốt, nhưng tôi nghĩ rằng nó tốt hơn để thêm một chức năng máy phát điện, trong một số tình huống không cần phải có được tất cả các nhóm. – Mithril

+0

@Mithril bạn có thể xây dựng những gì bạn nghĩ về trong https://github.com/valorize/MultiRegExp2/issues/5? – velop

0

Dựa trên ecma regular expression syntax Tôi đã viết một phân tích cú pháp tương ứng một phần mở rộng của lớp RegExp giải quyết vấn đề này (phương pháp exec được lập chỉ mục đầy đủ) cũng như các hạn chế khác của việc thực thi JavaScript RegExp ví dụ: tìm kiếm dựa trên nhóm & thay thế. Bạn có thể test and download the implementation here (cũng có sẵn như mô-đun NPM).

Việc thực hiện hoạt động như sau (ví dụ nhỏ):

//Retrieve content and position of: opening-, closing tags and body content for: non-nested html-tags. 
var pattern = '(<([^ >]+)[^>]*>)([^<]*)(<\\/\\2>)'; 
var str = '<html><code class="html plain">first</code><div class="content">second</div></html>'; 
var regex = new Regex(pattern, 'g'); 
var result = regex.exec(str); 

console.log(5 === result.length); 
console.log('<code class="html plain">first</code>'=== result[0]); 
console.log('<code class="html plain">'=== result[1]); 
console.log('first'=== result[3]); 
console.log('</code>'=== result[4]); 
console.log(5=== result.index.length); 
console.log(6=== result.index[0]); 
console.log(6=== result.index[1]); 
console.log(31=== result.index[3]); 
console.log(36=== result.index[4]); 

tôi đã cố gắng làm tốt công tác triển khai thực hiện từ @velop nhưng việc thực hiện dường như buggy ví dụ nó không xử lý một cách chính xác backreferences ví dụ "/ a (?:) bc (def (\ 1 ghi) xyz)/g" - khi thêm dấu ngoặc ở phía trước, sau đó yêu cầu \ 1 cần được tăng lên (trường hợp này không được thực hiện) .

+0

vui lòng sử dụng mô tả cách công cụ của bạn hoạt động. Đôi khi thật nguy hiểm khi tải xuống từ các không gian không xác định. – Alexan

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