Quantifier: *, +, ?, {n}, {n,}, {n,m}

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Một quantifier lặp lại một atom một số lần nhất định. Quantifier được đặt sau atom mà nó áp dụng.

Cú pháp

regex
// Greedy
atom?
atom*
atom+
atom{count}
atom{min,}
atom{min,max}

// Non-greedy
atom??
atom*?
atom+?
atom{count}?
atom{min,}?
atom{min,max}?

Note: Thêm ? sau {count} là cú pháp hợp lệ nhưng thực tế vô dụng. Vì {count} luôn khớp đúng count lần, atom{count}? hoạt động giống như atom{count}.

Tham số

atom

Một atom đơn lẻ.

count

Một số nguyên không âm. Số lần atom sẽ được lặp lại.

min

Một số nguyên không âm. Số lần tối thiểu atom có thể được lặp lại.

max Optional

Một số nguyên không âm. Số lần tối đa atom có thể được lặp lại. Nếu bỏ qua, atom có thể được lặp lại bao nhiêu lần tùy ý.

Mô tả

Một quantifier được đặt sau một atom để lặp lại nó một số lần nhất định. Nó không thể tự xuất hiện một mình. Mỗi quantifier có thể chỉ định số tối thiểu và tối đa mà một pattern phải được lặp lại.

Quantifier Tối thiểu Tối đa
? 0 1
* 0 Infinity
+ 1 Infinity
{count} count count
{min,} min Infinity
{min,max} min max

Đối với cú pháp {count}, {min,}, và {min,max}, không thể có khoảng trắng xung quanh các số — nếu không, nó trở thành pattern literal.

js
const re = /a{1, 3}/;
re.test("aa"); // false
re.test("a{1, 3}"); // true

Hành vi này được sửa trong Unicode-aware mode, trong đó các dấu ngoặc nhọn không thể xuất hiện theo nghĩa đen mà không cần thoát. Khả năng sử dụng {} theo nghĩa đen mà không cần thoát là cú pháp không dùng nữa để tương thích web, và bạn không nên dựa vào nó.

js
/a{1, 3}/u; // SyntaxError: Invalid regular expression: Incomplete quantifier

Đây là lỗi cú pháp nếu số tối thiểu lớn hơn số tối đa.

js
/a{3,2}/; // SyntaxError: Invalid regular expression: numbers out of order in {} quantifier

Quantifiers có thể khiến capturing groups khớp nhiều lần. Xem trang capturing groups để biết thêm thông tin về hành vi trong trường hợp này.

Mỗi kết quả khớp lặp lại không phải là cùng một chuỗi.

js
/[ab]*/.exec("aba"); // ['aba']

Quantifiers mặc định là greedy (tham lam), có nghĩa là chúng cố gắng khớp càng nhiều lần càng tốt cho đến khi đạt đến giá trị tối đa, hoặc cho đến khi không thể khớp thêm nữa. Bạn có thể làm cho một quantifier non-greedy bằng cách thêm ? sau nó. Trong trường hợp này, quantifier sẽ cố gắng khớp càng ít lần càng tốt, chỉ khớp thêm lần nếu không thể khớp phần còn lại của pattern với số lần lặp lại này.

js
/a*/.exec("aaa"); // ['aaa']; the entire input is consumed
/a*?/.exec("aaa"); // ['']; it's possible to consume no characters and still match successfully
/^a*?$/.exec("aaa"); // ['aaa']; it's not possible to consume fewer characters and still match successfully

Tuy nhiên, ngay khi regex khớp thành công chuỗi tại một chỉ số nào đó, nó sẽ không thử các chỉ số tiếp theo, mặc dù điều đó có thể dẫn đến việc tiêu thụ ít ký tự hơn.

js
/a*?$/.exec("aaa"); // ['aaa']; the match already succeeds at the first character, so the regex never attempts to start matching at the second character

Greedy quantifiers có thể thử ít lần lặp lại hơn nếu không thể khớp phần còn lại của pattern.

js
/[ab]+[abc]c/.exec("abbc"); // ['abbc']

Trong ví dụ này, [ab]+ trước tiên tham lam khớp "abb", nhưng [abc]c không thể khớp phần còn lại của pattern ("c"), vì vậy quantifier bị giảm để chỉ khớp "ab".

Greedy quantifiers tránh khớp vô hạn các chuỗi rỗng. Nếu số lần khớp tối thiểu đã đạt được và không có ký tự nào được tiêu thụ bởi atom tại vị trí này, quantifier dừng khớp. Đây là lý do tại sao /(a*)*/.exec("b") không dẫn đến vòng lặp vô hạn.

Greedy quantifiers cố gắng khớp càng nhiều lần càng tốt; nó không tối đa hóa độ dài của kết quả khớp. Ví dụ, /(aa|aabaac|ba)*/.exec("aabaac") khớp "aa" rồi "ba" thay vì "aabaac".

Quantifiers áp dụng cho một atom đơn lẻ. Nếu bạn muốn lượng hóa một pattern dài hơn hoặc một disjunction, bạn phải nhóm nó. Quantifiers không thể được áp dụng cho assertions.

js
/^*/; // SyntaxError: Invalid regular expression: nothing to repeat

Trong Unicode-aware mode, lookahead assertions có thể được lượng hóa. Đây là cú pháp không dùng nữa để tương thích web, và bạn không nên dựa vào nó.

js
/(?=a)?b/.test("b"); // true; the lookahead is matched 0 time

Ví dụ

Xóa HTML tags

Ví dụ sau xóa các HTML tags được bao trong dấu ngoặc nhọn. Lưu ý việc sử dụng ? để tránh tiêu thụ quá nhiều ký tự cùng một lúc.

js
function stripTags(str) {
  return str.replace(/<.+?>/g, "");
}

stripTags("<p><em>lorem</em> <strong>ipsum</strong></p>"); // 'lorem ipsum'

Có thể đạt được hiệu ứng tương tự với kết quả khớp tham lam, nhưng không cho phép pattern lặp lại khớp >.

js
function stripTags(str) {
  return str.replace(/<[^>]+>/g, "");
}

stripTags("<p><em>lorem</em> <strong>ipsum</strong></p>"); // 'lorem ipsum'

Warning: Đây chỉ để minh họa — nó không xử lý > trong giá trị thuộc tính. Hãy sử dụng HTML sanitizer phù hợp như HTML sanitizer API thay thế.

Xác định vị trí các đoạn Markdown

Trong Markdown, các đoạn được phân cách bởi một hoặc nhiều dòng trống. Ví dụ sau đếm tất cả các đoạn trong một chuỗi bằng cách khớp hai hoặc nhiều ngắt dòng.

js
function countParagraphs(str) {
  return str.match(/(?:\r?\n){2,}/g).length + 1;
}

countParagraphs(`
Paragraph 1

Paragraph 2
Containing some line breaks, but still the same paragraph

Another paragraph
`); // 3

Warning: Đây chỉ để minh họa — nó không xử lý ngắt dòng trong các khối mã hoặc các phần tử block Markdown khác như tiêu đề. Hãy sử dụng Markdown parser phù hợp thay thế.

Thông số kỹ thuật

Specification
ECMAScript® 2027 Language Specification
# prod-Quantifier

Tương thích trình duyệt

Xem thêm