重复由量词指定,量词可以跟在以下任何一项之后
一般重复量词通过在花括号(大括号)中给出两个数字,用逗号分隔来指定允许匹配的最小和最大数量。这两个数字必须小于 65536,第一个数字必须小于或等于第二个数字。例如:z{2,4}
匹配 "zz"、"zzz" 或 "zzzz"。单独的右括号不是特殊字符。如果省略第二个数字,但逗号存在,则没有上限;如果第二个数字和逗号都被省略,则量词指定所需匹配的精确数量。因此 [aeiou]{3,}
至少匹配 3 个连续的元音,但可能匹配更多,而 \d{8}
恰好匹配 8 个数字。出现在量词不允许的位置的左括号,或与量词语法不匹配的左括号,将被视为文字字符。例如,{,6} 不是量词,而是四个字符的文字字符串。
允许使用量词 {0},这会导致表达式表现得好像前面的项和量词不存在一样。
为了方便起见(以及为了与历史版本兼容),三个最常见的量词有单字符缩写
* |
等效于 {0,} |
+ |
等效于 {1,} |
? |
等效于 {0,1} |
可以通过在可以匹配任何字符的子模式后面跟上没有上限的量词来构造无限循环,例如:(a?)*
早期版本的 Perl 和 PCRE 曾经在编译时对这种模式给出错误。但是,由于在某些情况下这可能很有用,因此现在接受了这种模式,但是如果子模式的任何重复实际上没有匹配任何字符,则循环将被强制中断。
默认情况下,量词是“贪婪的”,也就是说,它们尽可能多地匹配(最多允许的次数),而不会导致模式的其余部分失败。贪婪性导致出现问题的一个经典例子是尝试匹配 C 程序中的注释。这些注释出现在序列 /* 和 */ 之间,并且在序列中,可能出现单独的 * 和 / 字符。尝试通过对字符串 /* first comment */ not comment /* second comment */
应用模式 /\*.*\*/
来匹配 C 注释会失败,因为它会匹配整个字符串,这是由于 .* 项的贪婪性所致。
但是,如果量词后面跟着一个问号,那么它就变成懒惰的,并且改为匹配尽可能少的次数,因此模式 /\*.*?\*/
对 C 注释做了正确的事情。各种量词的含义没有改变,只是首选的匹配次数。不要将问号在此处的用法与它自身用作量词的用法混淆。由于它有两个用途,因此它有时会显示为双重,如 \d??\d
,它首选匹配一位数字,但如果这是模式其余部分匹配的唯一方式,则可以匹配两位数字。
如果设置了 PCRE_UNGREEDY 选项(Perl 中没有此选项),那么量词默认不是贪婪的,但可以通过在它们后面加上问号来使各个量词变为贪婪。换句话说,它反转了默认行为。
后面跟着 +
的量词是“占有的”。它们尽可能多地吃掉字符,并且不返回以匹配模式的其余部分。因此 .*abc
匹配 "aabc",但 .*+abc
不匹配,因为 .*+
吃掉了整个字符串。占有量词可用于加快处理速度。
当带括号的子模式用大于 1 的最小重复次数或有限的最大次数进行量化时,编译后的模式需要更多存储空间,这与最小值或最大值的大小成比例。
如果模式以 .* 或 .{0,} 开头,并且设置了 PCRE_DOTALL 选项(等效于 Perl 的 /s),从而允许 . 匹配换行符,那么模式将隐式锚定,因为后面的任何内容都将针对主题字符串中的每个字符位置进行尝试,因此在第一个位置之后在任何位置重试整体匹配都没有意义。PCRE 将这种模式视为它前面有 \A。在已知主题字符串不包含换行符的情况下,在模式以 .* 开头时设置 PCRE_DOTALL 以获得此优化,或者使用 ^ 明确地指示锚定是值得的。
当捕获的子模式重复时,捕获的值是匹配最后一次迭代的子字符串。例如,在 (tweedle[dume]{3}\s*)+
匹配 "tweedledum tweedledee" 之后,捕获的子字符串的值是 "tweedledee"。但是,如果存在嵌套的捕获子模式,则相应的捕获值可能已在之前的迭代中设置。例如,在 /(a|(b))+/
匹配 "aba" 之后,第二个捕获的子字符串的值是 "b"。