02.正则表达式
准备:
—安装RegExpBuddy软件——专门测试正则表达式是否正确的软件
—或是找一个正则表达式在线测试网站
1.正则表达式——Regular Expression
什么是:
正则表达式,是专门描述字符串中字符出现规则的表达式。
为什么:
因为程序不认识人类语言中的词汇,所以才需要程序员用正则表达式教程序认识人类语言中的词汇。
可用于:
1.验证字符串格式
2.查找敏感词
定义正则表达式:
(1).普通字符
所有的单个大小写字母、数字都是一个正则表达式,用以匹配单个字符,这个字符与它本身相同,简单来讲,就是一个关键词原文。
—例如:"我是"
关键词匹配的过程:
在RegExp Buddy中
—查找一句话中是否包含敏感词“我是”
—如果将一句话中的“我是”,换成“我事”,还能查询出来吗?
(2).字符集
问题:
第二个字符换成另一个同音字,就匹配不到了
解决:
字符集
什么是:
—字符集是规定一位字符上多种备选字的列表
—只要规则中某一位字符上有多种备选字时,就用字符集
如何:
[备选字列表]
例如:
匹配时,只要与[]中任意一个字符匹配,就算满足规则
字符集匹配过程:
如果再连上前边写死的“我”字规则,可匹配三种词:
在RegExp Buddy中
—定义一个规则同时匹配“我是” ,“我事” ,“我时” 三种敏感词
答案: 我[是时事]
—扩展:修改规则,使其进一步匹配“卧是”
答案: [我卧][是时事]
—[我卧][是事时]匹配过程:
再例如:
常用手机号规则:
— 第一位:1
— 第二位:3、4、5、6、7、8、9中选其中一个
— 后 9位:每一位上都是在0~9数字之间任选其一
—结果:
问题:
如果每个数字都写很麻烦。
解决:
简写:如果[]中部分备选字符连续,可以使用-省略中间字符
例如:
手机号规则中:
[3456789] 可简写为 [3-9] 读作 3到9
[0123456789] 可简写为 [0-9] 读作 0到9
所以,手机简写形式:
1[3-8][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]
其它简写:
要匹配 一位小写 字母 : [a-z] 共26个
要匹配 一位大写 字母 : [A-Z] 共26个
要 匹 配 一 位 字 母 : [A-Za-z] 共52个
要匹配一位字母或数字:[0-9A-Za-z] 共62个
要 匹 配 一 位 汉 字:[\u4e00-\u9fa5]
19968 ~ 40869 共20902个
使用字符集简写:
在RegExp Buddy中
—利用字符集简写定义车牌号规则:
— 第一位:1位汉字
— 第二位:1位大写字母
— 第三位:·
— 后五位:每一位都是一位大写字母或数字
—答案:
[\u4e00-\u9fa5][A-Z]·[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]
(3).预定义字符集
正则表达式语法为四种最常用的字符集定义了最简化写法,称为预定义字符集。
包括:
要 匹 配 一 位 数 字 : \d 等效于 [0-9]
要匹配一位字母、数字或_: \w 等效于 [0-9A-Za-z_]
要 匹 配 一 位 空 字 符 :\s 可匹配 空格、制表符、Tab等空白
要匹配所有文字 (通配符) : .
所以,利用预定义字符集简写手机号规则为:
1[3-8]\d\d\d\d\d\d\d\d\d
问题:
手机号规则中\d写了9遍,车牌号规则中[0-9A-Z]也写了五遍,也很不方便。
原因:
一个字符集(\d或[0-9])只能匹配一位字符,要匹配9位字符,就必须重复写9遍。
程序用规则匹配字符串,就像彩票兑奖一样,是逐字逐个规则匹配。
不但内容要符合规则,位数首先要一致。
[\u4e00-\u9fa5][A-Z]·[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]
解决:
使用数量词。
(4).数量词
什么是:
数量词,是专门规定一个字符集出现次数的规则
何时:
今后,只要一个字符集在规则中可能连续反复出现多次,就要用数量词以简写方式定义出现次数。
如何:
数量词紧跟在其修饰的字符集之后,默认修饰相邻的前一个字符集
例如:
利用数量词进一步简写手机号规则中,可进一步简写为:
1[3-8]\d{9} \d{9} 相当于 \d*9次
使用数量词:
利用数量词进一步简写车牌号规则,可进一步简写为:
[\u4e00-\u9fa5][A-Z]·[0-9A-Z]{5}
问题:
接收短信验证码时,网站验证码有时4位,有时6位,并不确定,怎么办?
其实,数量词包括两大类:
1). 有明确数量边界的数量词
字符集{n} 表示字符集必须重复n次,不能多也不能少
例如:
\d{4,6} 表示4位数字
字符集{n,m} 表示字符集至少重复n次,最多重复m次,
例如:
\d{4,6} 表示4到6位数字
字符集{n,} 表示字符集匹配的内容至少重复n次,多了不限
例如:
\d{6,} 表示6位以上数字
2). 没有明确数量边界的数量词
* 表示可有可无,多了不限
\s*
+ 表示至少一次,多了不限
\s+
? 表示可有可无,最多一次
\s?
在RegExp Buddy中
—匹配手机短信中的验证码:连续的4位~6位数字
答案: \d{4,6}
—匹配字符串中的一组连续空字符
答案: \s+
(5).选择和分组
问题:
屏蔽敏感词时,输入者把字换成拼音就查不出来了
错误的做法:
直接将拼音放入[]中作为字符集中的备选
比如:
[草cao]
希望:
草 或 cao
原因:
字符集只认识单个字,不认识一组拼音
正确做法:
1).选择
什么是:
选择,是指在多个子规则中选其一匹配
何时:
今后,只要在多个子规则中选其一匹配时,就用选择
如何:
子规则1 | 子规则2
读作:
满足规则1 或 满足规则2
例如:
草 | cao
问题:
如果规则写成“我草|cao” 呢?
希望是:
我草 或 我cao
实际却是:
我草 | cao
原因:
因为“|”选择符只分左右,不考虑单个字符
解决:
使用分组。
2).分组
什么是:
分组,将多个子规则视为一组,再和分组外的规则匹配
何时:
只要希望将多个子规则视为一个整体,再和其它规则匹配时,就用分组
如何:
其它规则(多个子规则)
例如:
—匹配一个“草” 字或“cao”这个拼音
答案: 草|cao
—匹配“我草”或“我cao”
答案: 我(草|cao)
使用选择和分组:
问题1:
同时验证敏感字同音字或拼音,我草、我艹、我cao、我槽
答案:我 ([草艹槽]|cao)
问题2:
“我” 字也可能是“卧”或“wo”
答案:([我卧]|wo)([草艹槽]|cao)
问题3:
可能在中间加不确定个数的空字符:
答案:([我卧]|wo)\s*([草艹槽]|cao)
在RegExp Buddy中定义规则
—匹配“我草”
—匹配 “卧 槽”
—匹配 “wocao”,“我 草”等敏感词
—定义完整手机号规则:
分析:
+86或0086:(\+86|0086)
至少一个空字符 : \s+
之前所有,整体可有可无,最多一次: ()?
1
3~9
任选其一 9位数字
答案: ((\+86|0086)\s+)?1[3-8]\d{9}
—定义完整身份证号规则:
分析:
15位数字: \d{15} (一代身份证)
2位数字: \d\d
最后一位: 1位数字或Ⅹ: [0-9Ⅹ]
最后三位 可有可无,最多一次 (最后三位)?
答案:\d{15}(\d\d[0-9x])?
(6).指定匹配位置
一个字符串中三个位置比较特殊:
—1. 字符串开头
—2. 字符串结尾
—3. 英文句子中的每个单词中间的空白位置
如果只希望匹配特殊位置上的关键词时,就可用特殊符号表示特殊位置。
包括:
—1. ^ 表示字符串开头
—2. $ 表示字符串结尾
—3. \b 表示单词边界,可匹配:空格,标点符号,字符串开头和结尾等可将一个单词与其它单词分割开的符号。
例如:
匹配一组连续的空字符
—1. 匹配任意一组连续的空字符
—2. 仅匹配开头的空字
—3. 仅匹配结尾的空字符
—4. 同时匹配开头和结尾的空字符:
错误的做法:
^\s+$,表示从开头到结尾之间只能是空字符!
正确做法:
用“|”选择符,将整个规则强行一分为2
再比如:
找到每个单词首字母
—前边紧挨着单词边界的字母
附图片(不与博客内容匹配,仅参考):
英文单词整理
Regular Expression 正则表达式
Regular 规则
Expression 表达式 做一件事的一条程序的语句
\d digit (从 0 到 9 的任何一个)数字,数位
\s space (可利用的)空地,空间;空格
\w word 单词;词;字;
\b boundary 边界