场景与实训 - 每周每月练习 ¶
作者: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="(.+)"/));