假设我们有一个字符串 +7(903)-123-45-67,并且想要找到它包含的所有数字。但与之前不同的是,我们对单个数字不感兴趣,只对全数感兴趣:7, 903, 123, 45, 67

数字是一个或多个 \d 的序列。用来形容我们所需要的数量的词被称为量词

数量 {n}

最明显的量词便是一对引号间的数字:{n}。在一个字符(或一个字符类等等)后跟着一个量词,用来指出我们具体需要的数量。

它有更高级的格式,用一个例子来说明:

确切的位数:{5}

\d{5} 表示 5 位的数字,如同 \d\d\d\d\d

接下来的例子将会查找一个五位数的数字:

  1. alert( "I'm 12345 years old".match(/\d{5}/) ); // "12345"

我们可以添加 \b 来排除更多位数的数字:\b\d{5}\b

某个范围的位数:{3,5}

我们可以将限制范围的数字放入括号中,来查找位数为 3 至 5 位的数字:\d{3,5}

  1. alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"

我们可以省略上限。那么正则表达式 \d{3,} 就会查找位数大于或等于 3 的数字:

  1. alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) ); // "345678"

对于字符串 +7(903)-123-45-67 来说,我们如果需要一个或多个连续的数字,就使用 \d{1,}

  1. let str = "+7(903)-123-45-67";
  2. let numbers = str.match(/\d{1,}/g);
  3. alert(numbers); // 7,903,123,45,67

缩写

大多数常用的量词都可以有缩写:

+

代表“一个或多个”,相当于 {1,}

例如,\d+ 用来查找所有数字:

  1. let str = "+7(903)-123-45-67";
  2. alert( str.match(/\d+/g) ); // 7,903,123,45,67

?

代表“零个或一个”,相当于 {0,1}。换句话说,它使得符号变得可选。

例如,模式 ou?r 查找 o,后跟零个或一个 u,然后是 r

所以他能够在 color 中找到 or,以及在 colour 中找到 our

  1. let str = "Should I write color or colour?";
  2. alert( str.match(/colou?r/g) ); // color, colour

*

代表着“零个或多个”,相当于 {0,}。也就是说,这个字符可以多次出现或不出现。

接下来的例子将要寻找一个后跟任意数量的 0 的数字:

  1. alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1

将它与 '+'(一个或多个)作比较:

  1. alert( "100 10 1".match(/\d0+/g) ); // 100, 10

更多示例

量词是经常被使用的。它们是构成复杂的正则表达式的主要模块之一,我们接着来看更多的例子。

正则表达式“浮点数”(带浮点的数字):\d+\.\d+

实现:

  1. alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345

正则表达式“打开没有属性的 HTML 标记”,比如 <span><p>/<[a-z]+>/i

实现:

  1. alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body>

我们查找字符 '<' 后跟一个或多个英文字母,然后是 '>'

正则表达式“打开没有属性的HTML标记”(改进版):/<[a-z][a-z0-9]*>/i

更好的表达式:根据标准,HTML 标记名称可以在除了第一个位置以外的任意一个位置有一个数字,比如 <h1>

  1. alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>

正则表达式“打开没有属性的HTML标记”:/<\/?[a-z][a-z0-9]*>/i

我们在标记前加上了一个可选的斜杆 /?。必须用一个反斜杠来转义它,否则 JavaScript 就会认为它是这个模式的结束符。

  1. alert( "<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

创建一个正则表达式来查找省略号:连续 3(或更多)个点。

例如:

  1. let reg = /你的正则表达式/g;
  2. alert( "Hello!... How goes?.....".match(reg) ); // ..., .....

解决方案

Solution:

  1. let reg = /\.{3,}/g;
  2. alert( "Hello!... How goes?.....".match(reg) ); // ..., .....

需要注意的是,点号(.)是一个特殊字符,因此我们需要将其转义并作为 \. 插入语句。

针对 HTML 颜色的正则表达式

创建一个正则表达式来搜寻格式为 #ABCDEF 的 HTML 颜色值:首个字符 # 以及接下来的六位十六进制字符。

一个例子:

  1. let reg = /...你的正则表达式.../
  2. let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2 #12345678";
  3. alert( str.match(reg) ) // #121212,#AA00ef

P.S. 在这个任务中,我们不需要其他的颜色格式,比如 #123rgb(1,2,3) 等。

解决方案

我们需要寻找 # 字符,后跟六个十六进制字符。

一个十六进制字符可以被描述为 [0-9a-fA-F]。如果我们使用 i 标识,那么只需要 [0-9a-f]

然后我们可以用量词 {6} 来查找这六个。

因此,我们得到正则表达式:/#[a-f0-9]{6}/gi

  1. let reg = /#[a-f0-9]{6}/gi;
  2. let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2"
  3. alert( str.match(reg) ); // #121212,#AA00ef

问题是其从更长的序列中匹配了颜色值:

  1. alert( "#12345678".match( /#[a-f0-9]{6}/gi ) ) // #123456

为了解决这个问题,我们可以在末尾加上 \b

  1. // color
  2. alert( "#123456".match( /#[a-f0-9]{6}\b/gi ) ); // #123456
  3. // not a color
  4. alert( "#12345678".match( /#[a-f0-9]{6}\b/gi ) ); // null