Làm cách nào để nắm bắt một số lượng nhóm tùy ý trong JavaScript Regexp?


81

Tôi mong đợi dòng JavaScript này:

"foo bar baz".match(/^(\s*\w+)+$/)

để trả lại một cái gì đó như:

["foo bar baz", "foo", " bar", " baz"]

nhưng thay vào đó, nó chỉ trả về kết quả phù hợp được chụp cuối cùng:

["foo bar baz", " baz"]

Có cách nào để có được tất cả các trận đấu đã bắt không?

Câu trả lời:


90

Khi bạn lặp lại một nhóm chụp, trong hầu hết các phiên bản, chỉ có lần chụp cuối cùng được giữ lại; mọi ảnh chụp trước đó đều bị ghi đè. Trong một số trường hợp, chẳng hạn như .NET, bạn có thể nhận được tất cả các bản chụp trung gian, nhưng đây không phải là trường hợp của Javascript.

Có nghĩa là, trong Javascript, nếu bạn có một mẫu với N nhóm bắt, bạn chỉ có thể chụp chính xác N chuỗi cho mỗi trận đấu, ngay cả khi một số nhóm đó được lặp lại.

Vì vậy, nói chung, tùy thuộc vào những gì bạn cần làm:

  • Nếu đó là một tùy chọn, thay vào đó hãy phân tách trên các dấu phân cách
  • Thay vì khớp /(pattern)+/, có thể khớp /pattern/g, có thể trong một execvòng lặp
    • Xin lưu ý rằng hai điều này không hoàn toàn tương đương, nhưng nó có thể là một tùy chọn
  • Thực hiện đối sánh đa cấp:
    • Chụp nhóm lặp lại trong một trận đấu
    • Sau đó, chạy một regex khác để phá vỡ trận đấu đó

Người giới thiệu


Thí dụ

Dưới đây là một ví dụ về đối sánh <some;words;here>trong một văn bản, sử dụng một execvòng lặp, sau đó tách ra ;để lấy các từ riêng lẻ ( xem thêm trên Ideone.com ):

var text = "a;b;<c;d;e;f>;g;h;i;<no no no>;j;k;<xx;yy;zz>";

var r = /<(\w+(;\w+)*)>/g;

var match;
while ((match = r.exec(text)) != null) {
  print(match[1].split(";"));
}
// c,d,e,f
// xx,yy,zz

Mẫu được sử dụng là:

      _2__
     /    \
<(\w+(;\w+)*)>
 \__________/
      1

Trận đấu này <word>, <word;another>, <word;another;please>vv Nhóm 2 được lặp đi lặp lại để nắm bắt bất kỳ số từ, nhưng nó chỉ có thể giữ cho chụp cuối cùng. Toàn bộ danh sách các từ được nhóm 1 nắm bắt; chuỗi này sau đó splitnằm trên dấu phân cách dấu chấm phẩy.

Câu hỏi liên quan


7

Làm thế nào về điều này? "foo bar baz".match(/(\w+)+/g)


Mã của bạn hoạt động nhưng việc thêm cờ toàn cục vào ví dụ của tôi sẽ không giải quyết được vấn đề: "foo bar baz" .match (/ ^ (\ s * \ w +) + $ / g) sẽ trả về ["foo bar baz"]
disc0dancer,

nó sẽ hoạt động nếu bạn thay đổi nó thành biểu thức chính quy của @ Jet bên dưới. "foo bar baz".match(/\w+/g) //=> ["foo", "bar", "baz"]. nó bỏ qua chuỗi được so khớp ở phía trước nhưng vẫn là một sự thay thế hợp lý.
Jed Schneider

6

Trừ khi bạn có yêu cầu phức tạp hơn về cách tách các chuỗi của mình, bạn có thể tách chúng và sau đó trả lại chuỗi ban đầu cùng với chúng:

var data = "foo bar baz";
var pieces = data.split(' ');
pieces.unshift(data);

1
Đây cuối cùng chỉ là một lời khuyên mà tôi cần để cảnh tỉnh tôi thực tế rằng, ít nhất đối với ứng dụng hiện tại của tôi, tôi không cần bất cứ thứ gì phức tạp hơn split ().
Hephaestus

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.