一、是什么
正则表达式是具有特殊语法的字符串,用来表示指定字符或字符串在另一个字符串中出现的情况。也可以说是一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。
作用:
验证字符串、查找字符串、替换字符串、提取字符串。
典型的应用场景:
表单验证、网络爬虫、编写底层框架、日志分析。
构成:
//定界符、gim模式修正符、模式规则
注意事项:
正则是一门独立的语言,各种语言都支持对正则的使用。
在JavaScript中,直接使用//作为定界符即可,不需要加单引号或双引号。
在PHP中,则需要加上单引号或双引号,最好是使用单引号。
正则有两个系列,一是perl系列,二是posix系列。目前使用较多的是perl系列,效率稍高,js实现的只有perl系列,而php则两种都实现了。
在js中书写:
在js中使用:
字符串方式:
正则对象--RegExp
二、字符类:如何来描述或表示一个或多个字符
1.普通字符和元字符
普通字符:就是表示它自己,没有其他的含义。如,var r=/javascript/。大部分字符都是普通字符,比如a-z、0-9、A-Z、_等。
特殊字符:有其他的含义,不表示字符本身,通常称之为元字符。如,^ $ . * + ? | \ / ( ) [ ] { }。
注意,如果需要表示这个字符的本身,就需要转义,在其前面加\。
2.字符直接量:就是表示字符或字符串本身。如 var r = /javascript/。
直接使用字符本身、ASCII编码、Unicode编码来表示、转义字符
在这几种方式,注意一下unicode编码。
在匹配中文的时候,需要使用unicode编码。中文范围 \u4E00-\u9FA5。
3.简单字符类:就是把多个单独的字符放在中括号[]内,构成的一个字符集合。
eg.[abc] 可以简单理解为 a || b || c。也就是abc是或的关系,可以匹配三者之一,不能匹配字符ab、ac、bc、abc。
注意,[]中不能出现空格,如果有空格,就会匹配到空格本身。
4.反义字符类
针对的是简单字符类([abc])来使用的,只能用在[]中。在字符类内部添加脱字符 ^ 前缀,即是反义字符类。
注意,
反义,是针对的所有出现的字符进行定义,不是只针对第一个。
^ 只能出现在第一个位置,写在后面不起作用。
5.字符范围类:
用以匹配任意一个数字或小写字母,也是只针对简单字符类[]来使用的。不能再[]之外使用。
所谓的范围类,就是指定字符列表时,仅指定起止符,然后中间部分通过连字符-来表示,从而简化了表达式。
注意,
在字符类中可以混合使用简单字符、范围和反义字符。
字符范围类要遵守字符编码顺序来匹配,从小到大。否则出现语法错误。
连字符,只是在[]中才表示特定含义,在[]外仍是一个普通字符。
有了字符范围类,可以大大简化正则的编写。
用户名的格式:[a-zA-Z0-9_],当前只能表示一个字符。
中文的匹配:[\u4e00-\u9FA5],表示一个中文。
注意,使用u修饰符标识能够正确处理大于\uFFFF的Unicode字符,也就是说,会正确处理四个字节的UTF-16编码。
6.预定义字符类(推荐使用)
由于某些字符类比较常用,所以,就形成了一些固定格式,他们是通过一些特殊字符和转义序列来表示的,这就是预定义字符类。如 \w、\W、\d、\D、\s、\S、\b、\B
其实,范围类和反义字符类也是预定义字符类的一种。
切记切记切记,字符类只能表示一个字符,不能表示多个。
三、重复类
1.数量词
由于字符类只能匹配单个字符,需要结合数量词完成字符串匹配。如{n,m}、{n,}、{n}、?、+、*
直接写在字符类的后面就可以了。
2.贪婪匹配(字符串最后开始)
表达式默认是贪婪的形式。
在使用数量词的时候,会尽量多的去进行匹配。最大化匹配原则
首先,将整个字符串读取进来,看是否匹配。如果匹配,就返回结果。如果不匹配,去掉最后一个字符,然后再看是否匹配。如果匹配,返回结果,如果不匹配,再去掉倒数第二个字符,再进行匹配,以此类推。
弱贪婪性:贪婪的有限性,?、{n}、{n, m}
强贪婪性:贪婪的无限性,*、+、{n, }
3.惰性匹配(字符串最前开始)
与贪婪匹配相反,惰性匹配将遵循另一种算符,它将下查看字符串中的第一个字符是否匹配,如果匹配条件不够,就读入下一个字符,以此类推。
惰性匹配只需要在重复类后面添加?即可。
注意,问好?必须放在重复类字符后面。
四、高级匹配模式
1.选择
在进行字符串处理时,经常会遇到选择性问题。在正则中,选择使用管道符 | 表示。如:var r = /a|b/、var r = /\w+|\d+/
2.边界
正则提供了定位功能,所谓定位就是能够确定字符在字符串中的具体位置(如字符串的头部或尾部,或者单词的边界),也叫边界。如,^开始、$结尾、\b、\B
^和$
单词的边界\b,单词的边界,针对英文使用比较多。
注意,利用边界,完成实际的正则查询,
3.分组()
通过是小括号来包含一系列字符、字符类或者重复类量词,以实现处理各种特殊的字符序列。
如需求:
(1).如何匹配字符串"abcde-abcde-abcde-abcde-abcde"?
(2).如何匹配字符串 "2016-01-01 08:30:35",且分别获取年月日时分秒?
分组的应用价值:
把单独的项目进行分组,以便合成子表达式,这样就可以像处理一个独立的字符那样,使用|、+、*、?等元字符来处理它们。
通过分组可以在一个完整的模式中定义子模式,从而可以获取与子模式相匹配的部分。
在同一个正则表达式的后部可以引用前面的子表达式,从而实现反向引用。
4.反向引用
需求:对于给定数字字符串,找出所有四个数字连在一起的子串,并且这四个数字要满足第一位和第四位相同、第二位和第三位相同,如1331,2552。
反向引用分两个步骤:
捕获,使用分组就可以捕获,使用分组,在内存中就保存了分组的内容
引用,在当前这个正则中是可以使用 \数字来引用捕获的内容。\1 \2
[注意]:
如果有多个小括号,将遵循从左到右的顺序进行创建和编号的。
直接在定义分组的表达式中包含反向引用,使用\1、\2序列即可。
在字符串replace方法中,后续需要使用反向引用,使用$1、$2、$3等来实现。
使用match、test、search方法时,还可以使用RegExp.$n来获取反向引用。
反向引用使用场景,查找重复项,内容配对出现。
非引用型分组,在左括号后面加上一个?:即可,从而节省资源,提高效率。
非引用型分组:
另外,在只要使用了分组,就必定会在内存当中保存这个分组的内容,但是有时候我们并不需要保存这个内容。只需要将其作为一个独立的整体来处理它,并不会在后续引用它。此时,使用分组会降低效率。
--- 解决这种需求,非引用型分组。左括号后面加上一个?:
注意,使用了非引用型分组之后,那么就无法引用了。
5.零宽断言:Lookahead and Lookbehind Zero-Length Assertions。
需求:
(1).在字符串I'm singing while you're dancing中匹配以ing结尾的单词的前面部分
(2).字符串有bedroom,bedding中,匹配的是带room的bed,要的bed。
结论:要查某个字符串,这个字符串的后面紧跟着某种格式的内容。后面的这些内容,ing、room等,是作为查找的一个条件,但是并不是我们要查询的结果。因为在结果字符串中并没有出现,所以叫零宽。
正向预查和反向预查。
注意,这里的小括号不是分组。且在js中,只支持正向预查,而在php中,两种都支持。
6.匹配模式
需求:如何匹配字符串中的JavaScript或是javascript?
正则表达式提供了模式修正符,用来标记模式执行匹配的方式。在js中支持的标志有三种,如下:i、g、m
ignorecase,忽略大小写,i
global,全局,匹配多次,g
multiline,多行,m
这三个可以结合起来使用。
案例:
五、RegExp 对象
内置的对象。实例化方式,有两种:
直接new、直接量。
1.RegExp对象的属性
[注意]:
这些属性除lastIndex外只能获取,不能设置,所以一般很少使用。
lastIndex只有在调用test或exec方法时有效。
2.静态属性
直接通过RegExp来访问的。
RegExp.input
3.RegExp对象的方法
test只返回真假,而exec类似于字符串的match方法。
六、案例
正则用法很多,大部分都没有标准答案。可以在网站进行测试:http://tool.oschina.net/regex/
使用如:
用户名由3~16位的大小写字母、下划线、数字构成。
//用户名 $username = preg_match('/^[a-z0-9_-]{3,16}$/', $username); //isNumber preg_match("/^\d+$/", $number); //isSpelling preg_match('/^[a-zA-Z]{1,20}$/', $spelling); //护照、通行证 preg_match("/^[A-Z]{1,2}[0-9]{7,8}$/", $number); //isTWpass preg_match("/^T[0-9]{8}$/", $number); //正整数 preg_match("/^[1-9][0-9]*$/" , $number); //isHKMpass preg_match("/^W[0-9]{8}$/", $number); //密码 $pwd = preg_match('/^[a-z0-9_-]{6,18}$/', $pwd); //十六进制值 $sljzz = preg_match('/^#?([a-f0-9]{6}|[a-f0-9]{3})$/', $sljzz); //邮箱 $email1 = preg_match('/^([a-z0-9_\.-]+)@([\da-z\.-])\.([a-z\.]{2,6})$/', $email); $email2 = preg_match('/^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/', $email); //URL $url = preg_match('/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?$/', $url); //IP地址 $IP = preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/', $IP); $IP1 = preg_match('/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', $IP); //HTML标签 $html = preg_match('/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/', $html); //删除代码\\注释 $code = preg_match('/(?<!http:|\S)//.*$/', $code); //Unicode编码中的汉字范围 $Unicode = preg_match('/^[\u2E80-\u9FFF]+$/', $Unicode); //utf8,只允许2-10个汉字和· preg_match("/^[\x{4e00}-\x{9fa5}·]{2,10}$/u", $name); //手机号 $iphone = preg_match('/^1[34578]\d{9}$/', $iphone); //QQ号 $QQ = preg_match('/^[1-9]\d{4,10}$/', $QQ); //身份证 $id_card = preg_match('/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/i', $id_card); //时间data preg_match('/^20(\d){2}-(\d)*-(\d)*$/', $date); preg_match('/^20(\d){2}-(1[0-2]|0\d)-([0-2]\d|3[01])$/', $date);
//判断正负数
preg_match("/^[-\\+]?[\\d]*$/", -10);
七、常用总结
规则:
1.正则对象 new RegExp("sh","i");
在str中查找是否匹配pattern,
如果匹配就返回true,不匹配返回false。
匹配:有顺序关系。
2.字面量声明形式
//被称为定界符。
pattern=/sh/;
pattern.test(str)
3.正则函数
pattern.test():返回值是布尔型。
pattern.exec():返回的是数组,也只有第一个符合的结果。
str.match(pattern);返回所以符合的结构,类型是数组。
str.search(pattern):返回第一个符合的索引值。
str.replace(pattern,要替换的内容);根据模式进行字符串替换。
str.split(/,/);根据模式,模式定义的是分隔符,生成数组。
4.模式修饰符
i:insensitive不敏感,模式。
g:global全局的。
m:multi多行匹配
.+?:禁止贪婪
5.元字符
^:行首
$:行尾
[]:一个字符
[^a]:排除a
[a-z]:小写的26字母
[A-Z]:大写的26字母
[0-9]:0到9
[a-zA-Z0-9]:小写、大写、0到9
[\d]:digit数字。([0-9])
[\D]:非[0-9]
[\w]:[a-z],[A-Z],[0-9],_
.:任意一个非空字符
\s:空格;
量词,修饰前面的引导词的数量
?:0个或者1个;
*:任意个
+:至少一个
{n}:必须是n个
{n,}:至少n个。
{n,m}:最少n个,最多m个。
6.分组:()分隔开
捕获性分组:关注数量($n),也可以获取匹配的结果。
非捕获性分组:以?:开头:不关注数量,不可以获取匹配的结果。
(abc)@(yahoo).(com)
$1:(abc)
$2:(yahoo)
$3:(com)
7.模式分支
子模式|子模式|子模式
a<div>sdad</div>sfadfa<div>dsfasdf</div>asdfasdf