介绍

这周开始学习老姚大佬的《JavaScript 正则表达式迷你书》 , 然后习惯性的看完一遍后,整理一下知识点,便于以后自己重新复习。

我个人觉得:自己整理下来的资料,对于知识重现,效果不错。

感谢原书作者老姚,本文无意抄袭,只是作为自己知识点的整理,后续也会整理到自己的 JavaScript知识库——《Cute-JavaScript》 网站中。

另外,请读者们注意,这篇文章是知识点的整理,方便复习,所以不会介绍太详细,因为毕竟原书写得非常棒,刚入门的朋友,我还是建议看下原书。

然后可以看看这篇文章,来回顾重要知识点。

目录

  • 一、正则表达式字符匹配
  • 二、正则表达式位置匹配
  • 三、正则表达式括号的使用
  • 四、正则表达式回溯法原理
  • 五、正则表达式的拆分
  • 六、正则表达式的构建
  • 七、正则表达式编程

文章推荐(补充中)

工具推荐

一、正则表达式字符匹配

原书这么一句话,特别棒:正则表达式是匹配模式,要么匹配字符,要么匹配位置,要记住。

1. 两种模糊匹配

正则表达式的强大在于它的模糊匹配,这里介绍两个方向上的“模糊”:横向模糊和纵向模糊。

  • 横向模糊匹配

即一个正则可匹配的字符串长度不固定,可以是多种情况。

/ab{2,5}c/ 表示匹配: 第一个字符是 "a" ,然后是 2 - 5 个字符 "b" ,最后是字符 "c"

let r = /ab{2,5}c/g;
let s = "abc abbc abbbc abbbbbbc";
s.match(r); // ["abbc", "abbbc"]
  • 纵向模糊匹配

即一个正则可匹配某个不确定的字符,可以有多种可能。

/[abc]/ 表示匹配 "a", "b", "c" 中任意一个。

let r = /a[123]b/g;
let s = "a0b a1b a4b";
s.match(r); // ["a1b"]

2. 字符组

  • 范围表示法

可以指定字符范围,比如 [1234abcdUVWXYZ] 就可以表示成 [1-4a-dU-Z] ,使用 - 来进行缩写。

如果要匹配 "a", "-", "z" 中任意一个字符,可以这么写: [-az][a\-z][az-]

  • 排除字符组

即需要排除某些字符时使用,通过在字符组第一个使用 ^ 来表示取反,如 [^abc] 就表示匹配除了 "a", "b", "c" 的任意一个字符。

  • 常见简写形式
字符组 具体含义
\d 表示 [0-9],表示一位数字。
\D 表示 [^0-9],表示除数字外的任意字符。
\w 表示 [0-9a-zA-Z_],表示数字、大小写字母和下划线。
\W 表示 [^0-9a-zA-Z_],表示非单词字符。
\s 表示 [\t\v\n\r\f],表示空白符,包含空格、水平制表符、垂直制表符、换行符、回车符、换页符。
\S 表示 [^\t\v\n\r\f],表示非空白字符。
. 表示 [^\n\r\u2028\u2029] 。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。

然后表示任意字符,就可以使用 [\d\D][\w\W][\s\S][^] 任意一个。

3. 量词

量词也称重复,常用简写如下:

量词 具体含义
{m,} 表示至少出现 m 次。
{m} 等价于 {m, m} ,表示出现 m 次。
? 等价于 {0, 1} ,表示出现或不出现。
+ 等价于 {1, } ,表示至少出现1次。
* 等价于 {0, } ,表示出现任意次,也有可能不出现。
  • 贪婪匹配和惰性匹配

在正则 /\d{2,4}/ ,表示数字连续出现 2 - 4 次,可以匹配到 2 位、 3 位、4 位连续数字。

但是在 贪婪匹配/\d{2,4}/g ,会尽可能多匹配,如超过 4 个,就只匹配 4 个,如有 3 个,就匹配 3 位。

而在 惰性匹配/\d{2,4}?/g ,会 尽可能少 匹配,如超过 2 个,就只匹配 2 个,不会继续匹配下去。

let r1 = /\d{2,4}/g;
let r2 = /\d{2,4}?/g;
let s = "123 1234 12345";
s.match(r1); // ["123", "1234", "1234"]
s.match(r2); // ["12", "12", "34", "12", "34"]
惰性量词 贪婪量词
{m,m}? {m,m}
{m,}? {m,}
?? ?
+? +
*? *

4. 多选分支

即提供多个子匹配模式任选一个,使用 |(管道符)分隔,由于分支结构也是惰性,即匹配上一个后,就不会继续匹配后续的。

格式如:(r1|r2|r3),我们就可以使用 /leo|pingan/ 来匹配 "leo""pingan"

let r = /leo|pingan/g;
let s = "leo cool,pingan good.";
s.match(r);// ["leo", "pingan"] // 多选分支的惰性表现
let r1 = /leo|leooo/g;
let r2 = /leooo|leo/g;
let s = "leooo";
s.match(r1);// ["leo"]
s.match(r2);// ["leooo"]

5. 案例分析

匹配字符,无非就是字符组、量词和分支结构的组合使用。

  • 十六进制颜色值匹配
let r = /#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}/g;
let s = "#ffaacc #Ff00DD #fFF #01d #9Gd";
s.match(r); // ["#ffaacc", "#Ff00DD", "#fFF", "#01d"]
  • 时间和日期匹配
// 时间 12:23 或 01:09
let r = /^([01][0-9]|[2][0-3]):[0-5][0-9]$/;
r.test("23:25"); // true
r.test("03:05"); // true // 时间 12:23 或 1:9
let r = /^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/;
r.test("23:25"); // true
r.test("03:05"); // true
r.test("3:5"); // true // 日期 yyyy-mm-dd
let r = /^[0-9]{4}-(0[1-9]|[1][0-2])-(0[1-9]|[12][0-9]|3[01])$/;
r.test("2019-09-19"); // true
r.test("2019-09-32"); // false
  • Windows操作系统文件路径匹配

盘符使用 [a-zA-Z]:\\ ,这里需要注意 \ 字符需要转义,并且盘符不区分大小写;

文件名或文件夹名,不能包含特殊字符,使用 [^\\:*<>|"?\r\n/] 表示合法字符;

并且至少有一个字符,还有可以出现任意次,就可以使用 ([^\\:*<>|"?\r\n/]+\\)* 匹配任意个 文件夹\

还有路径最后一部分可以是 文件夹 ,即没有 \ 于是表示成 ([^\\:*<>|"?\r\n/]+)?

let r = /^[a-zA-Z]:\\([^\\:*<>|"?\r\n/]+\\)*([^\\:*<>|"?\r\n/]+)?$/;
r.test("C:\\document\\leo\\a.png"); // true
r.test("C:\\document\\leo\\"); // true
r.test("C:\\document"); // true
r.test("C:\\"); // true
  • id匹配

如提取 <div id="leo" class="good"></id> 中的 id="leo"

let r1 = /id=".*"/;    // tips1
let r2 = /id=".*?"/; // tips2
let r3 = /id="[^"]*"/; // tips3 let s = '<div id="leo" class="good"></id>';
s.match(r1)[0]; // id="leo" class="good"
s.match(r2)[0]; // id="leo"
s.match(r3)[0]; // id="leo"

tips1:由于 . 匹配双引号,且 * 贪婪,就会持续匹配到最后一个双引号结束。

tips2:使用惰性匹配,但效率低,有回溯问题。

tips3:最终优化。

二、正则表达式位置匹配

位置匹配,就是要匹配每个字符两边的位置。

ES5 中有6个位置: ^$\b\B(?=p)(?!p)

另外把位置理解成空字符是非常有用的:

/^^hello$$/.test('hello');  // true
/^^^hello$$/.test('hello'); // true

1. ^ 和 $

^ 匹配开头,多行中匹配行开头。

$ 匹配结尾,多行中匹配行结尾。

"hello".replace(/^|$/g, "#"); // "#hello#"
"hello\nleo\nhaha".replace(/^|$/gm, "#");
/*
#hello#
#leo#
#haha#
*/

多行匹配模式使用 m 修饰符。

2. \b\B

\b 匹配单词边界,即 \w\W 之间的位置,包括 \w^ 之间的位置,和 \w$ 之间的位置。

\B\b 相反,即非单词边界,匹配中除去 \b,剩下的都是 \B 的。

也就是 \w\w\W\W^\W\W$ 之间的位置。。

"[HI] Leo_1.mp4".replace(/\b/g,"#");
// "[#HI#] #Leo_1#.#mp4#" "[HI] Leo_1.mp4".replace(/\B/g,"#");
// "#[H#I]# L#e#o#_#1.m#p#4"

3. (?=p)(?!p)

p 为一个子模式,即 (?=p) 匹配前面是 p 的位置,而 (?!p) 则匹配前面不是 p 的位置。

"hello".replace(/(?=l)/g, "#");
// "he#l#lo" "hello".replace(/(?!l)/g, "#");
// "#h#ell#o#"

4. 相关案例

  • 匹配数字千位分隔符
// 匹配最后一个逗号
"12345678".replace(/(?=\d{3}$)/g, ","); // "12345,678" // 匹配所有逗号
"12345678".replace(/(?=(\d{3})+$)/g, ","); // "12,345,678" // 匹配其余
"123456789".replace(/(?=(\d{3})+$)/g, ","); // ",123,456,789" // 修改
"123456789".replace(/(?!^)(?=(\d{3})+$)/g, ","); // "12,345,678" // 其他形式
"12345678 123456789".replace(/(?!\b)(?=(\d{3})+\b)/g, ",");
// (?!\b) 等于 \B ,要求当前是一个位置,但不是 \b 前面的位置
// "12,345,678 123,456,789"
  • 数据格式化
let num = 1888;
num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ",").replace(/^/,"$$ ");
// "$ 1,888.00"
  • 验证密码
// 密码长度 6-12 位数字或字母
let r = /^[0-9A-Za-z]{6,12}$/; // 必须包含一个字符(数字) + 密码长度 6-12 位数字或字母
let r = /(?=.*[0-9])^[0-9A-Za-z]{6,12}$/; // 必须包含两个个字符(数字和小写字符) + 密码长度 6-12 位数字或字母
let r = /(?=.*[0-9])(?=.*[a-z])^[0-9A-Za-z]{6,12}$/; r.test("aa1234566"); // true
r.test("1234566"); // false // 密码长度 6-12 位数字或字母
// 即 不能全是数字 或 不能全是大写或小写字母
let r = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;

三、正则表达式括号的使用

简单理解:括号提供了分组,便于我们使用它。

通常有两种引用情况:在JS代码中引入,和在正则表达式中引入

分组和分支结构,主要是强调括号内是一个整体,即提供子表达式。

  • 分组如 /(ab)+/g 匹配连续出现的 ab
  • 分支结构如 /(a|b)+/g 匹配出现的 ab 表达式。

1.分组引用

如在日期匹配的时候,就可以这么改造:

// 原来
let r = /\d{4}-\d{2}-\d{2}/; // 现在
let r = /(\d{4})-(\d{2})-(\d{2})/;
  • 提取数据
"2019-03-14".match(r);
r.exec("2019-03-14");
// ["2019-03-14", "2019", "03", "14", index: 0, input: "2019-03-14"] RegExp.$1; // "2019"
RegExp.$2; // "03"
RegExp.$3; // "14"
  • 替换

yyyy-mm-dd 转成 mm/dd/yyyy

"2019-03-14".replace(r, "$2/$3/$1");
// 等价于
"2019-03-14".replace(r, function(){
return RegExp.$2 + '/' + RegExp.$3 + '/' + RegExp.$1;
});

2. 反向引用

使用 \n 表示第 n 个分组,比如 \1 表示第 1 个分组:

let r = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
r.test("2019-03-15");
r.test("2019/03/15");
r.test("2019.03.15");
r.test("2019-03/15");
  • 多个括号嵌套

按照开括号的顺序:

let r = /^((\d)(\d(\d)))\1\2\3\4$/;
let s = "1231231233";
r.test(s);
console.log([RegExp.$1,RegExp.$2,RegExp.$3,RegExp.$4]);
// ["123", "1", "23", "3"]
  • 特殊情况

\10 表示的是第 10 个分组,若要匹配 \0 时,使用 (?:\1)0\1(?:0)

let r = /(1)(2)(3)(4)(5)(6)(7)(8)(9)(#) \10+/;
let s = "123456789# #####";
r.test(s); // true
  • 当引用不存在的分组

如匹配 \2 是前面不存在,则匹配 \2 本身,即对 2 的转义,不同浏览器可能不同:

let r = /\1\2\3\4/;
r.test("\1\2\3\4"); // true
"\1\2\3\4".split('');// ["", "", "", ""]
  • 分组后面有量词

当分组后面有量词的话,则捕获的是最后一次的匹配:

"12345".match(/(\d)+/); // ["12345", "5", index: 0, input: "12345"]

/(\d)+ \1/.test("12345 1"); // false
/(\d)+ \1/.test("12345 5"); // true

3. 相关案例

这里只写出核心代码。

  • 模拟字符串 trim 方法
// 1 匹配首尾空白符,替换成空字符
" aaa ".replace(/^\s+|\s+$/g, ""); // "aaa" // 2 匹配整个字符串,再用引用提取对应数据
" aaa ".replace(/^\s*(.*?)\s*$/g, "$1");// "aaa"
  • 每个单词首字母大写
"hi leo hi boy!".toLowerCase().replace(
/(?:^|\s)\w/g,
c => c.toUpperCase()
);
// "Hi Leo Hi Boy!"
  • 驼峰化 和 中划线化
"-leo-and-pingan".replace(/[-_\s]+(.)?/g,
(match, c) => c ? c.toUpperCase() : ''
);
// "LeoAndPingan" "LeoAndPingan".replace(/([A-Z])/g, "-$1").replace(
/[-_\s]+g/,"-"
).toLowerCase();
// "-leo-and-pingan"
  • 匹配成对HTML标签

匹配成对标签 <h1>leo<\h1>,而不匹配不成对标签 <h1>leo<\h2>

let r = /<([^>]+)>[\d\D]*<\/\1>/;
r.test("<h1>leo leo leo</h1>"); // true
r.test("<a>leo leo leo</a>"); // true
r.test("<h1>leo leo leo</h2>"); // false

四、正则表达式回溯法原理

概念理解起来比较容易。

比如用 /ab{1,3}c/ 去匹配下面两个字符串。

  • 当匹配 abbbc,按顺序匹配,到了第 3 个 b 后,直接匹配 c,这样就没有回溯。

  • 当匹配 abbc,按顺序匹配,到了第 2 个 b 后,由于规则是 b{1,3} ,则会继续往下匹配,然后发现下一位是 c,于是回退到前一个位置,重新匹配,这就是回溯。

另外像 /".*"/ 来匹配 "abc"de 的话,就会有三个回溯情况,为了减少不必要的回溯,我们可以把正则修改为 /"[^"]*"/

介绍

回溯法,也称试探法,本质上是深度优先探索算法,基本思路是:匹配过程中后退到之前某一步重新探索的过程。

1. 常见的回溯形式

  • 贪婪量词

多个贪婪量词挨着存在,并相互冲突时,会看匹配顺序,深度优先搜索:

"12345".match(/(\d{1,3})(\d{1,3})/);
// ["12345", "123", "45", index: 0, input: "12345"]
  • 惰性量词

有时候会因为回溯,导致实际惰性量词匹配到的不是最少的数量:

"12345".match(/(\d{1,3}?)(\d{1,3})/);
// 没有回溯的情况 ["1234", "1", "234", index: 0, input: "12345"] "12345".match(/^\d{1,3}?\d{1,3}$/);
// 有回溯的情况 ["12345", index: 0, input: "12345"]
  • 分支结构

分支机构,如果一个分支整体不匹配,会继续尝试剩下分支,也可以看成一种回溯。

"candy".match(/can|candy/); // ["can", index: 0, input: "candy"]

"candy".match(/^(?:can|candy)$/); // ["candy", index: 0, input: "candy"]

2. 本章小结

简单总结:一个个尝试,直到,要么后退某一步整体匹配成功,要么最后试完发现整体不匹配。

  • 贪婪量词:买衣服砍价,价格高了,便宜点,再便宜点。

  • 懒惰量词:卖衣服加价,价格低了,多给点,再多给点。

  • 分支结构:货比三家,一家不行换一家,不行再换。

五、正则表达式的拆分

拆分正则代码块,是理解正则的关键。

在 JavaScrip 正则表达式有以下结构:

  • 字面量: 匹配一个具体字符,如 a 匹配字符 a
  • 字符组: 匹配一个有多种可能性的字符,如 [0-9] 匹配任意一个数字。
  • 量词: 匹配一个连续出现的字符,如 a{1,3} 匹配连续最多出现 3 次的a字符。
  • 锚: 匹配一个位置,如 ^ 匹配字符串的开头。
  • 分组: 匹配一个整体,如 (ab) 匹配 ab 两个字符连续出现。
  • 分支: 匹配一个或多个表达式,如 ab|bc 匹配 abbc 字符。

另外还有以下操作符:

优先级 操作符描述 操作符
1 转义符 \
2 括号和方括号 (...)/(?:...)/(?=...)/(?!...)/[...]
3 量词限定符 {m}/{m,n}/{m,}/?/*/+
4 位置和序列 ^/$/\元字符/一般字符
5 管道符 |

Tips:优先级从上到下,由高到低。

1. 注意要点

  • 匹配字符串整体

不能写成 /^abc|bcd$/ ,而是要写成 /^(abc|bcd)$/

  • 量词连缀问题

需要匹配:每个字符是 a/b/c 中其中一个,并且字符串长度是 3 的倍数:

不能写成 /^[abc]{3}+$/ ,而是要写成 /([abc]{3})+/

  • 元字符转义问题

元字符就是正则中的特殊字符,当匹配元字符就需要转义,如:

^$.*+?|\/()[]{}=!:-

// "[abc]"  => /\[abc\]/ 或者 /\[abc]/
// "{1,3}" => /\{1\}/ 或者 /\{1}/ 因为不构成字符组

2. 案例分析

  • 身份证号码
/^(\d{15}|\d{17})[\dxX]$/.test("390999199999999999");// true
  • IPV4地址

需要好好分析:

let r = /^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/

六、正则表达式的构建

正则的构建需要考虑以下几点的平衡:

  • 匹配预期的字符串
  • 不匹配非预期的字符串
  • 可读性和可维护性
  • 效率

我们还需要考虑这么几个问题:

  • 是否需要使用正则

如能使用其他 API 简单快速解决问题就不需要使用正则:

"2019-03-16".match(/^(\d{4})-(\d{2})-(\d{2})/); // 间接获取 ["2019", "03", "16"]
"2019-03-16".split("-"); // ["2019", "03", "16"] "?id=leo".search(/\?/); // 0
"?id=leo".indexOf("?"); // 0 "JavaScript".match(/.{4}(.+)/)[1]; // "Script"
"JavaScript".substring(4); // "Script"
  • 是否需要使用复杂正则

/(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/

将这个正则拆分成多个小块,如下:

var regex1 = /^[0-9A-Za-z]{6,12}$/;
var regex2 = /^[0-9]{6,12}$/;
var regex3 = /^[A-Z]{6,12}$/;
var regex4 = /^[a-z]{6,12}$/;
function checkPassword (string) {
if (!regex1.test(string)) return false;
if (regex2.test(string)) return false;
if (regex3.test(string)) return false;
if (regex4.test(string)) return false;
return true;
}

1. 准确性

即需要匹配到预期目标,且不匹配非预期的目标。

  • 匹配固定电话

如需要匹配下面固定电话号码,可以分别写出对应正则:

055188888888     => /^0\d{2,3}[1-9]\d{6,7}$/
0551-88888888 => /^0\d{2,3}-[1-9]\d{6,7}$/
(0551)88888888 => /^0\d{2,3}-[1-9]\d{6,7}$/

然后合并:

let r = /^0\d{2,3}[1-9]\d{6,7}$|^0\d{2,3}-[1-9]\d{6,7}$|^\(0\d{2,3}\)[1-9]\d{6,7}$/

然后提取公共部分:

let r = /^(0\d{2,3}|0\d{2,3}-|\(0\d{2,3}\))[1-9]\d{6,7}$/

再优化:

let r = /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/
  • 匹配浮点数

先确定,符号部分([+-])、整数部分(\d+)和小数部分(\.\d+)。

1.23、+1.23、-1.23  => /^[+-]?\d+\.\d+$/
10、+10、-10 => /^[+-]?\d+$/
.2、+.2、-.2 => /^[+-]?\.\d+$/

整理后:

let r = /^[+-]?(\d+\.\d+|\d+|\.\d+)$/;

// 考虑不匹配 +.2 或 -.2
let r = /^([+-])?(\d+\.\d+|\d+|\.\d+)$/; // 考虑不匹配 012 这类 0 开头的整数
let r = /^[+-]?(\d+)?(\.)?\d+$/;

2. 效率

正则表达式运行过程:

  1. 编译
  2. 设定起始位置
  3. 尝试匹配
  4. 若匹配失败则返回前一步重新匹配
  5. 返回匹配成功失败的结果

我们常常优化对 3 和 4 步进行优化:

  • 使用具体字符组替代通配符,消除回溯

/"[^"]*"/ 代替 /".*?"/

  • 使用非捕获型分组

当不需要使用分组引用和反向引用时,此时可以使用非捕获分组。

/^[-]?(?:\d\.\d+|\d+|\.\d+)$/ 代替 /^[-]?(\d\.\d+|\d+|\.\d+)$/

  • 独立出确定字符

加快判断是否匹配失败,进而加快移位的速度。

/aa*/ 代替 /a+/

  • 提取分支公共部分

减少匹配过程中可消除的重复。

/^(?:abc|def)/ 代替 /^abc|^def/

  • 减少分支的数量,缩小它们的范围

/rea?d/ 代替 /red|read/

七、正则表达式编程

这里要掌握正则表达式怎么用,通常会有这么四个操作:

  • 验证
  • 切分
  • 提取
  • 替换

1. 四种操作

  • 验证

匹配本质上是查找,我们可以借助相关API操作:

// 检查字符串是否包含数字
let r = /\d/, s = "abc123";
!!s.search(r); // true
r.test(s); // true
!!s.match(r); // true
!!r.exec(s); // true
  • 切分
"leo,pingan".split(/,/); // ["leo", "pingan"]

let r = /\D/, s = "2019-03-16";
s.split(r); // ["2019", "03", "16"]
s.split(r); // ["2019", "03", "16"]
s.split(r); // ["2019", "03", "16"]
  • 提取
// 提取日期年月日
let r = /^(\d{4})\D(\d{2})\D(\d{2})$/;
let s = "2019-03-16"; s.match(r); // ["2019-03-16", "2019", "03", "16", index: 0, input: "2019-03-16"]
r.exec(s); // ["2019-03-16", "2019", "03", "16", index: 0, input: "2019-03-16"]
r.test(s); // RegExp.$1 => "2019" RegExp.$2 => "03" RegExp.$3 => "16"
s.search(r);// RegExp.$1 => "2019" RegExp.$2 => "03" RegExp.$3 => "16"
  • 替换
// yyyy-mm-dd 替换成 yyyy/mm/dd
"2019-03-16".replace(/-/g, "/");

2. 相关API注意

  • searchmatch 参数问题

这两个方法会把字符串转换成正则,所以要加转义

let s = "2019.03.16";
s.search('.'); // 0
s.search('\\.'); // 4
s.search(/\./); // 4
s.match('.'); // ["2", index: 0, input: "2019.03.16"]
s.match('\\.'); // [".", index: 4, input: "2019.03.16"]
s.match(/\./); // [".", index: 4, input: "2019.03.16"] // 其他不用转义
s.split('.');
s.replace('.', '/');
  • match 返回结果的格式问题

match 参数有 g 会返回所有匹配的内容,没有 g 则返回标准匹配格式:

let s = "2019.03.16";
s.match(/\b(\d+)\b/); // ["2019", "2019", index: 0, input: "2019.03.16"]
s.match(/\b(\d+)\b/g); // ["2019", "03", "16"]
  • test 整体匹配时需要使用 ^$
/123/.test("a123b");    // true
/^123$/.test("a123b"); // false
/^123$/.test("123"); // true
  • split 的注意点

split 第二个参数是 结果数组的最大长度

"leo,pingan,pingan8787".split(/,/, 2); // ["leo", "pingan"]

使用正则分组,会包含分隔符:

"leo,pingan,pingan8787".split(/(,)/); // ["leo", ",", "pingan", ",", "pingan8787"]
  • 修饰符
修饰符 描述
g 全局匹配,即找到所有匹配的,单词是global
i 忽略字母大小写,单词是 ingoreCase
m 多行匹配,只影响 ^$,二者变成行的概念,即行开头和行结尾。单词是 multiline

文章到这结束,感谢阅读,也感谢老姚大佬的这本书

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787/Leo_Reading/issues
ES小册 js.pingan8787.com

微信公众号

《JavaScript 正则表达式迷你书》知识点小抄本的更多相关文章

  1. 《javascript正则表达式迷你书》笔记

    字符匹配攻略 横向匹配--通过量词 {m,n} {m,} {m} ? + * 贪婪匹配 后面跟?号 惰性匹配 纵向匹配--通过字符组 \d \D \w \W \s \S . \w表示[0-9a-zA- ...

  2. 《JavaScript 模式》知识点小抄本(下)

    介绍 最近开始给自己每周订个学习任务,学习结果反馈为一篇文章的输出,做好学习记录. 这一周(02.25-03.03)我定的目标是<JavaScript 模式>的第七章学习一遍,学习结果的反 ...

  3. 《JavaScript 模式》知识点小抄本(上)

    介绍 最近开始给自己每周订个学习任务,学习结果反馈为一篇文章的输出,做好学习记录. 这一周(02.25-03.03)我定的目标是<JavaScript 模式>的第七章学习一遍,学习结果的反 ...

  4. JavaScript Promise迷你书(中文版)

    最近,发现了一个很不错的关于Promise介绍的迷你电子版书,分享给大家: http://liubin.org/promises-book/#chapter4-advanced-promise (篇幅 ...

  5. JavaScript Promise迷你书(中文版)--再学习

    上次粗翻了一下,感觉没吃透,这次深入体会一下. <script> function getURL(URL) { return new Promise(function(resolve, r ...

  6. 推荐一本迷你中文书《JavaScript Promise迷你书(中文版)》

    https://github.com/azu/promises-book http://it-ebooks24.com/ebook/mastering-javascript-promises 传值,调 ...

  7. javascript正则表达式入门先了解这些

    前言 此内容由学习<JavaScript正则表达式迷你书(1.1版)>整理而来(于2020年3月30日看完).此外还参考了MDN上关于Regex和String的相关内容,还有ECMAScr ...

  8. JavaScript正则表达式知识点

    通过学习imooc课程<JavaScript正则表达式>http://www.imooc.com/video/12539,对视频教学内容做一个知识整理. 一个正则表达式在线工具:http: ...

  9. 《高性能javascript》一书要点和延伸(上)

    前些天收到了HTML5中国送来的<高性能javascript>一书,便打算将其做为假期消遣,顺便也写篇文章记录下书中一些要点. 个人觉得本书很值得中低级别的前端朋友阅读,会有很多意想不到的 ...

随机推荐

  1. ASP.NET Core 3.0 gRPC 身份认证和授权

    一.开头聊骚 本文算是对于 ASP.NET Core 3.0 gRPC 研究性学习的最后一篇了,以后在实际使用中,可能会发一些经验之文.本文主要讲 ASP.NET Core 本身的认证授权和gRPC接 ...

  2. hdu 1556 Color the ball (树状数组)

    Color the ballTime Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  3. 1 数据 & 图表

    瞎逼逼:虽然是统计专业,但学艺不精.大学受过的专业训练很少,妥妥学渣.因此工作后决定重新复习,阅读材料为贾俊平的<统计学>第7版.每周更新. 我不按照书里的逻辑顺序和所有知识点来写我的笔记 ...

  4. img标签不能直接作为body的子元素

    前几天在一本教材上看到关于HTML标签嵌套规则一节的时候,看到这么一句话,“把图像作为body元素的子元素直接插入到页面中,这样是不妥的,一是结构嵌套有误,二是图像控制不方便.”后面还给了一段代码演示 ...

  5. Javascript ----函数表达和形参实参

    1.函数是对象,函数名实际上是函数对象的指针 1.函数声明方式 (函数声明提前) function sum(num1,num2){return num1+num2;} 2.函数表达式 var sums ...

  6. ubuntu 16.04安装并启动openssh

    对于没有图形界面的linux系统,一般都会用到远程连接控制,,因此新安装的linux系统,在配好网络后,首先要安装的就是远程连接工具,ssh是常用的方法. ps -ef |grep ssh  //查看 ...

  7. 解析深度学习 语音识别实践 pdf下载

    链接:https://pan.baidu.com/s/1jd8_2nbz6M9e20lI3JdVGA  密码:1ikc 我从别人那里买的!可以友情赞助资瓷!

  8. Linux的curl和wget

    wget wget命令用来从指定的URL下载文件.wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕.如果是服 ...

  9. Xamarin.Forms学习系列之Android集成极光推送

    一般App都会有消息推送的功能,如果是原生安卓或者IOS集成消息推送很容易,各大推送平台都有相关的Sample,但是关于Xamarin.Forms的消息推送集成的资料非常少,下面就说下Xamarin. ...

  10. 设置颜色的函数:rgb,hsv,color palettes

    1.grb函数 (1)功能: 通过对给定的三个基本色红,绿,蓝的颜色饱和度(intensity)的设定,而创造颜色. 阿尔法透明度(alpha transparent):其值也能被指定,从0到max ...