jQuery源码学习(2)-正则表达式
由于jQuery源码中涉及到大量正则表达式,可以写篇博客整理正则表达式。
1、语法
1.1定义
正则表达式(regular expression)是一个描述字符模式的对象,ECMAScript的RegExp 类表示正则表达式,而String和RegExp都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数。可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。js中,正则表达式主要用来验证客户端的输入数据。
定义正则:
方式1:使用new关键字创建,var patt = new RegExp(pattern,modifiers); //RegExp对象
方式2:var patt = /pattern/modifiers;
参数1:pattern(模式)描述了表达式的模式;
参数2:modifiers(修饰符)用于指定全局匹配(g)、区分大小写的匹配(i)和多行匹配(m)。
模式和修饰符都能再添加双引号或单引号。
1.2规则
参考链接:http://www.runoob.com/jsref/jsref-obj-regexp.html
正则表达式元字符是包含特殊含义的字符。它们有一些特殊功能,可以控制匹配模式的方式。反斜杠后的元字符将失去其特殊含义。
字符类:单个字符和数字 [0-9A-Za-z]
元字符/元符号 匹配情况
. 匹配除换行符外的任意字符
[a-z0-9] 匹配括号中的字符集中的任意字符
[^a-z0-9] 匹配任意不在括号中的字符集中的字符
\d ==[0-9] 匹配数字
\D ==[^0-9] 匹配非数字,同[^0-9]相同
\w [0-9A-Za-z_] 匹配字母和数字及_
\W 匹配非(字母和数字及_)
字符类:空白字符
元字符/元符号 匹配情况
\0 匹配null 字符
\b 匹配空格字符
\n 匹配换行符
\r 匹配回车字符
\t 匹配制表符
\s 匹配空白字符、空格、制表符和换行符
\S 匹配非空白字符
字符类:锚字符
元字符/元符号 匹配情况
^ 行首匹配
$ 行尾匹配
字符类:重复字符
元字符/元符号 匹配情况
? 例如(x?) 匹配0个或1 个x
* 例如(x*) 匹配0个或任意多个x
+ 例如(x+) 匹配至少一个x
(xyz)+ 匹配至少一个(xyz)
{m,n} 例如x{m,n} n>=次数>=m 匹配最少m个、最多n个x
{n} 匹配前一项n次
{n,} 匹配前一项n次,或者多次
要表示出现次数(重复)——限定符
- a*表示字符a连续出现次数 >= 0 次
- a+表示字符a连续出现次数 >= 1 次
- a?表示字符a出现次数 0 或 1 次
- a{5}表示字符a连续出现次数 5 次
- a{5,}表示字符a连续出现次数 >= 5次
- a{5,10}表示字符a连续出现次数为 5到10次 ,包括5和10
2、正则应用
常用方法:
方法 | 描述 |
---|---|
search | 检索与正则表达式相匹配的第一个匹配项的索引。 |
match | 找到一个或多个正则表达式的匹配。 |
replace | 替换与正则表达式匹配的子串。 |
split | 把字符串分割为字符串数组。 |
举例:
<script type=
"text/javascript"
>
var
s =
"Abc123aBc"
;
alert(s.search(/abc/gi));
alert(s.search(/abc/gi));
// 即使设置的全局模式,每次search也是从开始向后查找
//match方法和正则表达式的exec()方法的作用是一样的,但是match会一次性把所有的匹配放在一个数组中,全部返回
alert(s.match(/abc/gi));
// Abc,aBc
alert(s.replace(/[ab]/gi,
"x"
));
//把a或b替换成x
var
ss = s.split(/[0-9]+/gi);
//用1个或多个数字切割。 Abc,aBc
alert(ss);
</script>
2.1 检验数字的JS正则表达式
2.2、校验字符的js正则表达式
2.3、特殊需求js正则表达式(常用test()函数在客户端验证)
^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
15 邮政编码(共6位数字,第一位不为0):/[1-9][0-9]{5}/ 或 [1-9]\d{5}(?!\d)
16 检验文件压缩包: /[\w]+\.zip|rar|gz/ //\w表示所有数字和字母加下划线
2.4、钱的输入格式
34 不能为空:/\S/
35 匹配空行:^(\s*)\n
原文链接:http://www.51xuediannao.com/javascript/zhengzedaquan.html
3、原理
3.1、 正则引擎
为什么正则能有效,因为有引擎,这和为什么JS能执行一样,有JS引擎,所谓正则引擎,可以理解为根据你的正则表达式用算法去模拟一台机器,这台机器有很多状态,通过读取待测的字符串,在这些状态间跳来跳去,如果最后停在了“终结状态”(Happy Ending),那么就Say I Do,否则Say You Are a Good Man。如此将一个正则表达式转换为一个可在有限的步数中计算出结果的机器,那么就实现了引擎。正则的引擎大致可分为两类:DFA和NFA
1. DFA (Deterministic finite automaton) 确定型有穷自动机
2. NFA (Non-deterministic finite automaton) 非确定型有穷自动机,大部分都是NFA
这里的“确定型”指,对于某个确定字符的输入,这台机器的状态会确定地从a跳到b,“非确定型”指,对于某个确定字符的输入,这台机器可能有好几种状态的跳法;这里的“有穷”指,状态是有限的,可以在有限的步数内确定某个字符串是被接受还是发好人卡的;这里的“自动机”,可以理解为,一旦这台机器的规则设定完成,就可以自行判断了,不要人看。
DFA引擎不需要进行回溯,所以匹配效率一般情况下要高,但是它并不支持捕获组,于是也就不支持反向引用和$这种形式的引用,也不支持环视(Lookaround)、非贪婪模式等一些NFA引擎特有的特性。
如果想更详细地了解正则、DFA、NFA,那么可以去看一下《计算理论》,然后你可以根据某个正则表达式自己画出一台自动机。
3.2、知识储备
n个字符,n+1个位置:如图所示:
理解“占有字符”和“零宽度”:
- 如果一个子正则表达式匹配到的是字符,而不是位置,而且会被保存到最终的结果中,那个这个子表达式就是占有字符的,比如/ha/(匹配ha)就是占有字符的;
- 如果一个子正则匹配的是位置,而不是字符,或者匹配到的内容不保存在结果中(其实也可以看做一个位置),那么这个子表达式是零宽度的,比如/read(?=ing)/(匹配reading,但是只将read放入结果中,下文会详述语法,此处仅仅举例用),其中的(?=ing)就是零宽度的,它本质代表一个位置。
占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却可以同时由多个零宽度的子表达式匹配。举个栗子,比如/aa/是匹配不了a的,这个字符串中的a只能由正则的第一个a字符匹配,而不能同时由第二个a匹配(废话);但是位置是可以多个匹配的,比如/\b\ba/是可以匹配a的,虽然正则表达式里有2个表示单词开头位置的\b元字符,这两个\b是可以同时匹配位置0(在这个例子中)的。
注意:我们说字符和位置是面向字符串说的,而说占有字符和零宽度是面向正则说的。
控制权和传动
这两个词可能在搜一些博文或者资料的时候会遇到,这里做一个解释先:
控制权是指哪一个正则子表达式(可能为一个普通字符、元字符或元字符序列组成)在匹配字符串,那么控制权就在哪。
传动是指正则引擎的一种机制,传动装置将定位正则从字符串的哪里开始匹配。
正则表达式当开始匹配的时候,一般是由一个子表达式获取控制权,从字符串中的某一个位置开始尝试匹配,一个子表达式开始尝试匹配的位置,是从前一子表达匹配成功的结束位置开始的。
举一个栗子,read(?=ing)ing\sbook匹配reading book,我们把这个正则看成5个子表达式read、(?=ing)、ing、\s、book,当然你也可以吧read看做4个单独字符的子表达式,只是我们这里为了方便这么看待。read从位置0开始匹配到位置4,后面的(?=ing)继续从位置4开始匹配,发现位置4后面确实是ing,于是断言匹配成功,也就是整一个(?=ing)就是匹配了位置4这一个位置而已(这里更能理解什么是零宽了吧),然后后面的ing再从位置4开始匹配到位置7,然后\s再从位置7匹配到位置8,最后的book从位置8匹配到位置12,整一个匹配完成。
讲的很详细的一篇博客:http://www.jb51.net/article/110516.htm