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