量词 +, *, ? 和 {n}
前言
假设我们有一个字符串 +7(903)-123-45-67,并且想要找到它包含的所有数字。但与之前不同的是,我们对单个数字不感兴趣,只对全数感兴趣:7, 903, 123, 45, 67。
数字是一个或多个 \d 的序列。用来形容我们所需要的数量的词被称为量词。
数量{n}、{m , n}、{n,}
最明显的量词便是一对引号间的数字:{n}。在一个字符(或一个字符类等等)后跟着一个量词,用来指出我们具体需要的数量。
它有更高级的格式,用一个例子来说明:
例子1:{5}
\d{5} 表示 5 位的数字,如同 \d\d\d\d\d。
接下来的例子将会查找一个五位数的数字:
console.log("I'm 12345 years old".match(/\d{5}/)); // [ '12345', index: 4, input: "I'm 12345 years old", groups: undefined ]例子2:\b\d{5}\b
我们可以添加 \b 来排除更多位数的数字:\b\d{5}\b。
console.log("123 1234 456 123456789".match(/\d{3}/g)) // [ '123', '123', '456', '123', '456', '789' ]
console.log("123 1234 456 123456789".match(/\b\d{3}\b/g)) //[ '123', '456' ]例子3:{3,5}
某个范围的位数:{3,5}
我们可以将限制范围的数字放入括号中,来查找位数为 3 至 5 位的数字:\d{3,5}
console.log("I'm not 12, but 1234 years old".match(/\d{3,5}/)); // "1234"
/*
[
'1234',
index: 16,
input: "I'm not 12, but 1234 years old",
groups: undefined
]
*/我们可以省略上限。那么正则表达式 \d{3,} 就会查找位数大于或等于 3 的数字:
console.log("I'm not 12, but 345678 years old".match(/\d{3,}/)); // "345678"
/*
[
'345678',
index: 16,
input: "I'm not 12, but 345678 years old",
groups: undefined
]
*/对于字符串 +7(903)-123-45-67 来说,我们如果需要一个或多个连续的数字,就使用 \d{1,}:
console.log("+7(903)-123-45-67".match(/\d{1,}/g)); // [ '7', '903', '123', '45', '67' ]缩写
大多数常用的量词都可以有缩写:
+
代表“一个或多个”,相当于 {1,}。
例如,\d+ 用来查找所有数字:
// + ==> {1,} 表示一个或多个
console.log("+7(903)-123-45-67".match(/\d+/g)); // [ '7', '903', '123', '45', '67' ]?
代表“零个或一个”,相当于 {0,1}。换句话说,它使得符号变得可选。
let str = "Should I write color or colour?";
// ? ==> {0,1} 可有可无
// ?前面的u 就变得可有可无了
console.log(str.match(/colou?r/g)); // [ 'color', 'colour' ]*
代表着“零个或多个”,相当于 {0,}。也就是说,这个字符可以多次出现或不出现。
// * ==> {0,}
console.log("100 10 1".match(/\d0*/g)) // [ '100', '10', '1' ]
// + ==> {1,}
console.log("100 10 1".match(/\d0+/g)) // [ '100', '10' ]更多示例
量词是经常被使用的。它们是构成复杂的正则表达式的主要模块之一,我们接着来看更多的例子。
例子1
正则表达式“浮点数”(带浮点的数字):\d+\.\d+
实现:
console.log( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // [ '12.345' ]例子2
正则表达式“打开没有属性的 HTML 标记”,比如 <span> 或 <p>:/<[a-z]+>/i
实现:
console.log( "<body> ... </body>".match(/<[a-z]+>/gi) ); // [ '<body>' ]我们查找字符 '<' 后跟一个或多个英文字母,然后是 '>'。
例子3
正则表达式“打开没有属性的HTML标记”(改进版):/<[a-z][a-z0-9]*>/i
更好的表达式:根据标准,HTML 标记名称可以在除了第一个位置以外的任意一个位置有一个数字,比如 <h1>。
console.log("<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi)); // [ '<h1>' ]例子4
正则表达式“打开没有属性的HTML标记”:/<\/?[a-z][a-z0-9]*>/i
我们在标记前加上了一个可选的斜杆 /?。必须用一个反斜杠来转义它,否则 JavaScript 就会认为它是这个模式的结束符。
console.log("<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi)); // [ '<h1>', '</h1>' ]更精确意味着更复杂
我们能够从这些例子中看到一个共同的规则:正则表达式越精确 —— 它就越长且越复杂。
例如,HTML 标记能用一个简单的正则表达式:
<\w+>。因为
\w代表任意英文字母或数字或'_',这个正则表达式也能够匹配非标注的内容,比如<_>。但它要比<[a-z][a-z0-9]*>简单很多。我们能够接受
<\w+>或者我们需要<[a-z][a-z0-9]*>?在现实生活中,两种方式都能接受。取决于我们对于“额外”匹配的宽容程度以及是否难以通过其他方式来过滤掉它们。
总结
我们想要匹配一个字符出现一次或者多次时,可以使用量词。
{5}:表示出现5次{1,3}:表示出现1到3次{0,1}:表示出现0次或者多次{1,}:表示出现1次或者多次{0,}:表示出现0次或者多次
缩写形式,如下
{5}→{5}{1,3}→{1,3}{0,1}→?{1,}→+{0,}→*