场景与实训 - 每周每月练习 ¶
- 作者:KK 
- 发表日期:2019.08.31 
前言 ¶
对于新手程序员来说,正则总是他们偶尔要用到又不怎么熟悉的部分,不容易自己写出一个匹配规则,要看一些基础资料才可以,在此我希望这篇文章里的一些练习过程能帮助大家快速熟悉正则。这个练习建议大家每月甚至每周都尽量练习一遍,练上十多遍就可以了。
练习工具:浏览器控制台 ¶
不过你是不是 Web 开发者,用浏览器控制台来调试练习是一个很便捷的方式哦,打开 Chrome 内核的浏览器,按 
输入/c\d+q/.test('abc123ddx')回车,结果是 false 表示匹配失败,因为它要求字母 c 后面跟一串数字再后面跟个字母 q ,我们改成/c\d+d/.test('abc123ddx')结果就为 true 了。
为了方便重复执行代码,以下变量使用了var声明而不是let声明。
练习1:+ 号基础、英数字匹配、回避干扰内容 ¶
- 提取句子里面的数字 - var str = '小明今年13岁了'; var matchResult = str.match(/\d+/); console.log('匹配结果的数量', matchResult.length); console.log('岁数是', matchResult[0]); //13 console.log('判断是否匹配', /\d+/.test(str)); //true var str = '小明今年13岁了'; var matchResult = str.match(/\d/); console.log('匹配结果的数量', matchResult.length); console.log('岁数是', matchResult[0]); //1 之所以不是13,是因为 \d 虽然代表数字,但只匹配1次,所以只匹配了第1个数字,用 \d+ 表示1个或多个连续的数字才能像开头那样匹配出13 var str = '小明今年13岁了,在上6年级'; var matchResult = str.match(/\d+/); console.log('匹配结果的数量', matchResult.length); //1 console.log('岁数是', matchResult[0]); //13 console.log('年级是', matchResult[1]); //undefined 这里匹配不到后面的 6 是因为只匹配了一次就停止了,要换成全局匹配模式,往下看全局模式- 表达式里的 - \d表示数字,后面的- +号表示前者的一个或多个,也就是一个或多个数字。
- 全局模式 - var str = '小明今年13岁了,在上6年级'; var matchResult = str.match(/\d+/g); //js只要在表达式后面加个g就可以,php要从preg_match函数换成preg_match_all函数,python要将serch或match换成findall函数,Java更加复杂,各种语言的全局匹配方式都不同 console.log('匹配结果的数量', matchResult.length); //2 console.log('岁数是', matchResult[0]); //13 console.log('年级是', matchResult[1]); //6
- 提取一句话里面的英数字 - var str = '小明的英文名是Jay'; var matchResult = str.match(/\w+/); console.log('提取到的英文名是', matchResult[0]); //Jay var str = '我的微信账号是kk5201314,你加我吧'; var matchResult = str.match(/\w+/); console.log('微信号是', matchResult[0]); //kk5201314
- 避开干扰的内容,提取你需要的内容 - var str = 'Hi! Marie,我的微信账号是kk5201314,你加我吧!'; var matchResult = str.match(/\w+/); console.log('结果不是个账号', matchResult[0]); //Hi var matchResult = str.match(/账号是\w+/); console.log('加上中文就好了', matchResult[0]); //账号是kk5201314 可是前面有中文 var matchResult = str.match(/账号是(\w+)/); console.log('只有账号了', matchResult[1]); //kk5201314 表达式里加括号说明它是你需要的,括号里表达式的匹配结果会追加在数组的后面,从下标1开始往后排- 表达式里的 - \w表示英文数字组合。
练习2:区间和枚举匹配 ¶
这里用到的知识点叫区间,用方括号括住,表示“某几个元素”
- 匹配指定的数字 - var str = '小明17岁'; console.log('判断里面是否有7或3', /[73]/.test(str)); //true console.log('判断里面是否有2或3或5', /[235]/.test(str)); //false console.log('判断里面是否有1到5之间的数字', /[1-5]/.test(str)); //true console.log('判断里面是否有0到9之间的数字', /[0-9]/.test('出租屋房号是263')); //true 0到9其实覆盖了所有数字了,因此跟 \d 是一样的 console.log('判断里面是否有0到8之间的数字', /[0-8]/.test('出租屋房号是999')); //false
- 匹配指定的英文字母 - var str = '我叫May'; console.log('判断里面是否有x或y', /[xy]/.test(str)); //true console.log('判断里面是否有b或c或q', /[bcq]/.test(str)); //false console.log('判断里面是否有a到d之间的字母(就是abcd)', /[a-d]/.test(str)); //true console.log('判断里面是否有a到z之间的字母', /[a-z]/.test(str)); //true 覆盖了所有字母了 console.log('判断里面是否有m或A或Y', /[mAY]/.test(str)); //false 因为是要匹配大小写的 console.log('判断里面是否有M或y', /[My]/.test(str)); //true console.log('判断里面是否有任何英文字母', /[a-zA-Z]/.test(str)); //true 大小写都涵盖
- 匹配英数字下划线 - var str = '我的账号是 Marie_223'; console.log('比如用于账号匹配', /[a-zA-Z0-9_]/.test('_')); //true console.log('比如用于账号匹配', /[a-zA-Z0-9_]/.test('marie')); //true console.log('比如用于账号匹配', /[a-zA-Z0-9_]/.test('443')); //true console.log('比如用于账号匹配', /[a-zA-Z0-9_]/.test('!')); //false console.log('比如用于账号匹配', /\w/.test('_')); //true console.log('比如用于账号匹配', /\w/.test('marie')); //true console.log('比如用于账号匹配', /\w/.test('443')); //true console.log('比如用于账号匹配', /\w/.test('!')); //false
- 匹配某些词组 - var str = '我叫May'; console.log(/(中国|美国)/.test('我是中国人')); //true console.log(/(中国|美国|德国)/.test('我是美国人')); //true console.log(/(中国|美国)/.test('我是法国人')); //false
练习3:连续次数 ¶
- 匹配连续3个字母a - var str = '昵称是aaa'; console.log(/a{3}/.test(str)); //true console.log(/a{2}/.test(str)); //true 连续2个也满足 console.log(/a{4}/.test(str)); //false 4个就没有了- 没错,次数就是用花括号包住的 
- 匹配连续2到3个字母a - console.log(/a{2,3}/.test('昵称是aa')); //true console.log(/a{2,3}/.test('昵称是aaa')); //true console.log(/a{2,3}/.test('昵称是axa')); //false- 花括号里用逗号隔开两个数字,左边是最小匹配数目,右边是最大匹配数目 
- 匹配最多或最小的连续次数 - 注意下面用了全局模式来匹配所有可能符合的内容 - //匹配2个或2个以上的连续字母 b ,也就是最少2个起 var str = '我的昵称是bbb,我有一台bb机,但我不是个傻b'; console.log(str.match(/b{2,}/g)); //bb 和 bbb ,但后面的单个b达不到连续2个以上就没匹配它了 //匹配最最多2个连续大写字母 I var str = '某国家的股票代码是 II{数字} 的格式,最少会有1个字母I,比如 II4572或I3143'; console.log(str.match(/I{,2}\d+/g)); //II4572 和 I ,但后面的单个b达不到连续2个以上就没匹配它了 var str = 'abcd'; console.log(/c{1,}/.test(str)); //true 至少有1个c没错 console.log(/h{0,}/.test(str)); //true 因为最小要求是0个,所以没有h也符合
练习4:任意字符 ¶
.这个点号在正则里是“任意字符”的意思,类似其SQL里的*号(通配符)
console.log(/a/.test('bat'), '看看有没有字母a,当然有'); //true
console.log(/a/.test('bt'), '看看有没有字母a,当然没有'); //false
console.log(/./.test('bt'), '看看有没有任意字符,那只要不是空就有'); //true
console.log(/./.test('')); //false
console.log(/b.t/.test('bat'), 'b 任意字母 再加个 t'); //true
console.log(/b.t/.test('bt'), 'b 和 t 没有任何字符,不满足'); //false
console.log(/bt/.test('bat')); //false
console.log(/b.{3}t/.test('babct'), '中间3个任意字符'); //true
console.log(/b.{2,3}t/.test('bact'), '中间2~3个任意字符'); //true
console.log(/b.{2,3}t/.test('bacxt'), '中间2~3个任意字符'); //true
console.log(/b.{2,3}t/.test('bacx99t'), '预期只要2~3个,实际上b和t之间却有5个'); //false
练习5:次数简写 ¶
- 匹配1次或多次 - var str = 'abc7d'; //是否存在1个数字 console.log(/\d/.test(str)); //true console.log(/\d{1}/.test(str)); //true console.log(/\d{1,}/.test(str)); //true console.log(/\d+/.test(str)); //true 注意这里的 + 号 console.log(/\d+/.test('abcd')); //false- +号的意思就是:匹配前面定义的那个内容1次或多次,其实跟- {1,}是等效的,是一个简写形式。- 下面匹配HTML里的图片地址试试: - console.log('<img src="http://xxx.com/123.jpg">'.match(/src="(.+)"/)); //匹配成功 console.log('<img src="">'.match(/src="(.+)"/)); //null
- 匹配0次或多次 - 其实就是 - *号,它跟- {0,}是等效的。- console.log('<img src="http://xxx.com/123.jpg">'.match(/src="(.*)"/)); //匹配成功 console.log('<img src="">'.match(/src="(.*)"/)); //也成功 //身份证号匹配测试 console.log(/\d{17}X*/.test('44281319990909343X'), '0个或多个X'); //true console.log(/\d{17}X*/.test('44281319990909343'), '0个或多个X'); //true console.log(/\d{17}X*/.test('4428131999090934'), '数字的字数不足'); //false //0个或多个空格,0个或多个分号 console.log('nickname = "小白兔";'.match(/nickname *= *"(.+)";*/)); //匹配成功 console.log('nickname = "小白兔";'.match(/nickname *= *"(.+)";*/)); //匹配成功 console.log('nickname="小白兔"'.match(/nickname *= *"(.+)";*/)); //匹配成功
练习6:行首、行尾、多行匹配 ¶
- 判断是否指定内容开头 - 在表达式前面加 - ^说明开始必须是某些内容- console.log(/^abc/.test('abcde')); //true console.log(/^bbc/.test('abcde')); //false console.log(/^\d+/.test('123开始!')); //true console.log(/^[a-zA-Z]+/.test('123开始!')); //false
- 判断是否以指定内容结尾 - 在表达式后面加 - $- console.log(/中国人$/.test('我是中国人')); //true console.log(/中国人$/.test('我是中国人!')); //false 多了个叹号 console.log(/中国人$/.test('我是美国人')); //false console.log(/\d+$/.test('我家话是12334567')); //true console.log(/[a-zA-Z]+$/.test('我家话是12334567')); //true
练习7:不要指定内容 ¶
- 匹配 Windows 后面不带 2000 的单词 - console.log(/Windows(?!2000)/.test('Windows2000')); //false console.log(/Windows(?!2000)/.test('Windows2008')); //true console.log(/Windows(?!2000|2008)/.test('Windows2008'), '后面带2000和2008都不要,内部用 | 隔开'); //false
- 不匹配 Windows 后面带数字 的单词 - 其实表达“不匹配某些内容”还可以在区间方括号( - [ ])里面以- ^开头表示这里的内容是不参与匹配的- console.log(/Windows(?!\d+)/.test('Windows2000')); //false console.log(/Windows[^\d]+/.test('Windows2000')); //false console.log(/Windows[^0-9]+/.test('Windows2000')); //false console.log(/Windows(?!\d+)/.test('WindowsXP')); //true console.log(/Windows[^\d]+/.test('WindowsXP')); //true console.log(/Windows[^0-9]+/.test('WindowsXP')); //true
练习8:空白、单词边界 ¶
- 匹配空格 - 用 - \s- console.log('<img src="http://xxx.com/123.jpg">'.match(/<img\s+src="(.+)"/)); //加多几个空格也一样 console.log('<img src="http://xxx.com/123.jpg">'.match(/<img\s+src="(.+)"/));
- 匹配tab符 - 其实 - \s代表了空白,包括了- 空格和- tab,注意鼠标拖选下面 img 后面的空白,能发现它是 tab 符,不是空格哦- console.log('<img src="http://xxx.com/123.jpg">'.match(/<img\s+src="(.+)"/));