量词:*、+、?、{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.

量词会将原子重复一定的次数。量词被置于其适用的原子项之后。

语法

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

// 非贪婪
atom??
atom*?
atom+?
atom{count}?
atom{min,}?
atom{min,max}?

参数

atom

单个原子项

count

非负整数,原子应当被重复的次数。

min

非负整数,原子可以被重复的最小次数。

max 可选

非负整数,原子可以被重复的最大次数。如果省略该参数,原子可根据需要重复多次。

描述

量词位于原子项之后,用于将原子项重复一定次数。它不能单独出现。每个量词都可以指定一个模式必须重复的最小和最大次数。

量词 最小值 最大值
? 0 1
* 0 Infinity
+ 1 Infinity
{count} count count
{min,} min Infinity
{min,max} min max

对于 {count}{min,}{min,max} 语法,数字周围不能有空格,否则就会变成字面字符模式。

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

这种行为在 Unicode 感知模式中得到了修正,在这种模式下,如果不使用转义语法,就不能按字面意思使用大括号。在不使用转义的情况下按字面意思使用 {} 的特性是一种为与 web 兼容而废弃的语法,不应依赖这种特性。

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

如果最小值大于最大值,会产生语法错误。

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

量词可导致捕获组多次匹配。有关这种情况下的行为的更多信息,请参阅捕获组页面。

每次重复匹配的字符串不必相同。

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

默认情况下,量词是贪婪的,这意味着它们会尝试尽可能多地匹配,直到达到最大值或无法继续匹配为止。你可以在量词后面添加 ?,使其成为非贪婪量词。在这种情况下,量词会尽量减少匹配次数,只有当重复匹配次数达到不可能匹配到模式的其余部分时,才会增加匹配次数。

js
/a*/.exec("aaa"); // ['aaa'];整个输入被消耗
/a*?/.exec("aaa"); // [''];可以不消耗任何字符,但仍能成功匹配
/^a*?$/.exec("aaa"); // ['aaa'];不可能消耗更少的字符而仍然匹配成功

不过,只要正则表达式在某个索引处成功匹配字符串,就不会再尝试后续索引,尽管这可能会导致消耗更少的字符。

js
/a*?$/.exec("aaa"); // ['aaa'];在第一个字符处已经匹配成功,因此该正则表达式不会尝试从第二个字符处开始匹配

如果无法与模式的其余部分匹配,贪婪量词可能会尝试较少的重复。

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

在本例中,[ab]+ 首先贪婪地匹配了 "abb",但 [abc]c 无法匹配模式的其余部分("c"),因此量词被简化为只匹配 "ab"

贪婪的量化符避免匹配无限多的空字符串。如果匹配的字符数达到最小值,且原子在该位置不再消耗更多字符,那么量化器就会停止匹配。这就是为什么 /(a*)*/.exec("b") 不会导致无限循环。

贪婪的量词会尽可能地匹配,而不会最大化匹配的长度。例如,/(aa|aabaac|ba)*/.exec("aabaac") 先匹配 "aa",然后匹配 "ba" 而不是 "aabaac"

量词适用于单个原子。如果要对较长的模式或选择表达式进行量化,必须对其进行分组。量词不能用于断言

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

Unicode 感知模式中,前向断言可以量化。这是一种为兼容 web 而过时的语法,不应依赖它。

js
/(?=a)?b/.test("b"); // true;前向匹配了零次

示例

移除 HTML 标签

下面的示例删除了用角括弧括起来的 HTML 标记。请注意使用 ? 以避免一次删除过多字符。

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

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

使用贪婪匹配可以达到同样的效果,但不允许重复模式与 > 匹配。

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

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

警告: 以上方法仅供演示——它无法处理属性值中的 >。请使用合适的 HTML 净化器。

定位 Markdown 段落

在 Markdown 中,段落由一个或多个空行分隔。下面的示例通过匹配两个或多个换行符来计算字符串中的所有段落。

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

警告: 以上方法仅供演示——它无法处理代码块或其他 Markdown 块元素(如标题)中的换行符。请使用合适的 Markdown 解析器。

规范

Specification
ECMAScript® 2025 Language Specification
# prod-Quantifier

浏览器兼容性

Report problems with this compatibility data on GitHub
desktopmobileserver
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Deno
Node.js
Quantifier: *, +, ?, {n}, {n,}, {n,m}

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support

参见