Javascript 量词 +, *, ? 和 {n}
假设我们有一个像这样 +7(903)-123-45-67
的字符串,并想要找到其中所有数字。但与之前不同的是,我们对单个数字不感兴趣,只对全数感兴趣:7, 903, 123, 45, 67
。
数字是一个或多个数字 \d
的序列。为了标记我们需要的数量,我们需要加一个 量词。
数量 {n}
最简单的量词便是大括号中的数字:{n}
。
在一个字符(或一个字符类,或 [...]
等)后附加一个量词,用来指出我们具体需要的数量。
它有一些高级的形式,让我们看一些例子:
确切的位数:{5}
\d{5}
表示 5 位数,与 \d\d\d\d\d
相同。
下面这个例子查找一个五位数的数字:
alert( "I'm 12345 years old".match(/\d{5}/) ); // "12345"
我们可以添加 \b
来排除位数更多的数字:\b\d{5}\b
。
范围:{3,5}
,匹配 3-5 个
要查找 3-5 位的数字,我们可以将限制写在花括号中:\d{3,5}
alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"
我们可以省略上限。
那么正则表达式 \d{3,}
就会查找位数大于等于 3
的数字:
alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) ); // "345678"
让我们回到字符串 +7(903)-123-45-67
。
我们如果需要一个及以上的数字,就使用 \d{1,}
:
let str = "+7(903)-123-45-67";
let numbers = str.match(/\d{1,}/g);
alert(numbers); // 7,903,123,45,67
缩写
大多数常用的量词都有简写形式:
+
代表“一个或多个”,与 {1,}
相同。
例如,\d+
用来查找所有数字:
let str = "+7(903)-123-45-67";
alert( str.match(/\d+/g) ); // 7,903,123,45,67
?
代表“零个或一个”,与 {0,1}
相同。换句话说,它使得符号变得可选。
例如,模式 ou?r
查找 o
,后跟零个或一个 u
,然后是 r
。
所以 colou?r
会找到 color
和 colour
:
let str = "Should I write color or colour?";
alert( str.match(/colou?r/g) ); // color, colour
*
代表“零个及以上”,与 {0,}
相同。也就是说,字符可以出现任何次数或者不出现。
例如,\d0*
查找一个数字后面跟着任意数量的零(可能有很多或没有)的数字:
alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1
将其与 +
(一个或更多)做比较:
alert( "100 10 1".match(/\d0+/g) ); // 100, 10
// 1 没有被匹配出来,因为 0+ 要求至少有一个 0
更多示例
量词是很常用的。它们是构成复杂正则表达式的主要“模块”,所以让我们看更多示例。
小数的正则表达式(带浮点的数字):\d+\.\d+
实现:
alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345
”没有特性(attribute)的打开的 HTML 标签(例如 <span>
或 <p>
)“的正则表达式。
-
最简单的:
/<[a-z]+>/i
alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body>
正则表达式查找的匹配项是字符
'<'
后跟一个或多个拉丁字母,然后是'>'
。 -
进阶版:
/<[a-z][a-z0-9]*>/i
根据标准,HTML 标签名称可以在除了第一个位置之外的任何位置有一个数字,例如
<h1>
。alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>
“打开或关闭的不带特性的 HTML 标签”的正则表达式:/<\/?[a-z][a-z0-9]*>/i
我们在模式开头附近添加了一个可选的斜杠 /?
。必须用一个反斜杠转义它,否则 JavaScript 会认为它是这个模式的结束符。
alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>
为了使正则表达式更精确,我们通常需要使其更复杂
我们能够从这些例子中看到一个共同的规则:正则表达式越精确 —— 它就越长越复杂。
例如,对于 HTML 标签,我们可以使用更简单的正则表达式:
<\w+>
。但是由于 HTML 对标签名称有更严格的限制,所以<[a-z][a-z0-9]*>
更可靠
我们可以使用
<\w+>
还是需要<[a-z][a-z0-9]*>
?
在实际开发中,这两种变体都是可以接受的。具体用哪个取决于我们对于“额外”匹配的宽容程度,以及通过其他方式将它们从结果中删除的困难程度。
任务
如何找到省略号 "..."?
创建一个正则表达式来查找省略号:连续 3(或更多)个点。
例如:
let regexp = /你的正则表达式/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....
解决方案
答案:
let regexp = /\.{3,}/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....
请注意,点(.)是一个特殊字符,所以我们必须对其进行转义,即将其插入为 \.
。
针对 HTML 颜色的正则表达式
创建一个正则表达式来查找格式为 #ABCDEF
的 HTML 颜色值:首个字符是 #
,后面紧接着的是六位的十六进制字符。
用例:
let regexp = /...你的正则表达式.../
let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2 #12345678";
alert( str.match(regexp) ) // #121212,#AA00ef
P.S. 在这个任务中,我们不需要其他的颜色格式,例如 #123
或 rgb(1,2,3)
等。
解决方案
我们需要寻找首个字符是 #
,后面紧接着的是六位的十六进制字符的匹配项。
一个十六进制字符可以描述为 [0-9a-fA-F]
。如果我们使用修饰符 i
,那么只需要 [0-9a-f]
。
然后我们可以使用量词 {6}
来查找其 6 个字符。
那么,我们得到正则表达式:/#[a-f0-9]{6}/gi
。
let regexp = /#[a-f0-9]{6}/gi;
let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2"
alert( str.match(regexp) ); // #121212,#AA00ef
问题是其从更长的序列中匹配了颜色值:
alert( "#12345678".match( /#[a-f0-9]{6}/gi ) ) // #123456
为了解决这个问题,我们可以在末尾加上 \b
:
// 颜色值
alert( "#123456".match( /#[a-f0-9]{6}\b/gi ) ); // #123456
// 不是颜色值
alert( "#12345678".match( /#[a-f0-9]{6}\b/gi ) ); // null
更多建议: