1) JavaScript 中的正则表达式JavaScript用RegExp的对象表示正则表达式。2) 创建JavaScript正则表达式a) re = ne
1) JavaScript 中的正则表达式JavaScript用RegExp的对象表示正则表达式。
2) 创建JavaScript正则表达式
a) re = new RegExp("a*b") // 使用字符串作为参数,而不是literals
b) re = /a*b/
上面2中方式都是创建一个正则表达式,/a*b/ 叫做正则表达式的字面值(literals)。
3) 了解正则表达式
a. 什么是正则表达式
JavaScript正则表达式是Perl正则表达式的子集。
正则表达式是一个用于匹配的模板(关于正则表达式,有很多不同的定义)。比如 /abc/ 就是用于匹配含有abc的所有的字符串。
b. 正则表达式的组成
正则表达式是由一系列的字符组成,比如 /abc/。具体来说包括:字母字符,数字字符,转义字符,标点(punctuation)字符。下面列举一些常用的正则表达式字符:
1. 数字字符和字母字符匹配该字符本身,比如说 /javascript/ 就是匹配含有javascript的字符串
2. \t 匹配 Tab(制表符)
3. \n 匹配 newline(换行)
4. \r 匹配回车
5. \s 匹配空字符
6. \S 匹配非空字符
7. \b 匹配字(word)边界,比如 /\bjavascript\b/ 匹配的字符串里,必须含有字javascript,而类似 123javascript22,这类的字符串无法与之匹配,注意,字边界中字是由数字,字母或下划线组成。
8. \B 匹配非字边界
9. ^ $ . * + ? = ! : | \ / ( ) [ ] { }
引用内容
上面^ $ . * + ? = ! : | \ / ( ) [ ] { }属于标点字符("和@不在其中),他们在正则表达式中有特殊的含义,假如我们要匹配 "abc?abc" 这个字符串的时候,就有问题了,因为 ? 是有特殊意义的,所以他们需要转义,也就是用 \? 来代替?,也就是,要用/abc\?abc/ 这个正则表达式来匹配上面的字符串,而不能用/abc?abc/。因为 " 没有特殊意义,所以我们使用的时候不需要转义,但是假如你转义了 \" ,也不会影响结果, \" 和 "是等效的,即对没有特殊意义的字符进行转义的结果和没转义一样。通常我们不去记JavaScript中用到了那些标点字符,只要是标点字符,如果不用特殊意义,我们就转义。
由于标点字符比较复杂,所以专门拿出来,再下面讲。
c. 标点字符的意义
1. 字符类,用标点字符[],例如:[abc]。注意字符类只能匹配长度为1的字符,这也是它为什么叫字符类的原因了。
[abc]可以匹配 a , b 或者 c。
[^abc]可以匹配非a,b,c的所有的字符。
[a-z0-9]表示a到z的所有字符和0-9的所有字符。也就是对于英文字符和数字字符可以使用"-"表示一个连续的集合。
. 点号,它可以表示所有的字符,除了换行之外。
\w,匹配所有的数字字符和字母字符以及"_",它等价于[0-9a-zA-Z_]
\W,大写的W,匹配所有的字符,不包括数字字符,字母字符,以及"_",它等价于[^0-9a-zA-Z_]
\d,所有数字,它等价于[0-9]
\D,所有非数字,它等价于[^0-9]
[\b],表示退格,注意,不加[],表示字(word)边界。
2. 重复
*,表示前面的字符出现0次或0次以上
+,表示前面的字符出现1次或1次以上
?,表示前面的字符出现0次或1次
{n,m},前面的字符重复次数在 n 到 m 次之间(n<=x<=m)
{n,},前面的字符重复次数大于等于n(x>=n)
{n},前面的字符重复的次数等于n(x==n)
3. 重复字符
处于上面符号之前的字符,叫重复字符。
4. 一些例子:
/a*/ 匹配 "aaa"
/a*/ 也匹配 "bbb",因为*表示重复0次或多次,因此会使得他们匹配,这应该注意,/a*/可以和任何字符串匹配。
5. 贪婪的重复(匹配)和非贪婪的重复(匹配)
/a*b/ 匹配 "aaaab"。我们说过a*可以匹配空字符串,也可以匹配 a 或者 aa ,aaa,aaaa,那这里到底是匹配什么呢?实际上,匹配过程一直继续下去,到第4个a,也就是这里的 a* 匹配到了 aaaa,匹配方式是贪婪的。也就是:尽可能多的让重复字符重复匹配。
在*,?,+,{n,m},{n,},{n}后面加上?就表示进行非贪婪的重复。所谓非贪婪的重复,就是说:重复字符仅进行一次成功匹配。但是,正则表达式还有一个必须准寻一个准则------正则表达式匹配完成的标志是,在被匹配的字符串中找到第一个可以匹配的位置或者并不存在与之匹配的串,匹配的过程是从被匹配串的第一个字母开始,一个一个继续下去的,当以第一个字母开始的子串无法被匹配的时候,才开始以第二字母为开始字母进行匹配。这句话之所以标记为红色,因为它十分重要,正确理解这句话,不仅对下面的分析有益,而且还是以后使用JavaScript RegExp对象的基础。我们来看看这个表达式:
/a*?b/ 明显,他匹配的是 "b",我们前面已经讲过非贪婪的重复是重复字符仅进行一次成功匹配,也就是 a*? 匹配空串,结果就是匹配 "b",虽然到目前为止还没有设计到程序设计,但是为了验证这个问题,这里给出一个代码:
程序代码
function f(regexp,str){
return str.search(regexp)
}
document.write(f(/a/,"b")+"<br />")
document.write(f(/a*?b/,"b")+"<br />")
document.write(f(/a*?b/,"aaab")+"<br />")
引用内容
结果显示
-1
0
0
这也就是说, /a*?b/ 能匹配 "b",同时,/a*?b/ 也能匹配 "aaab"。这不就和 /a*b/的匹配结果一样吗?其实因为 a*? 第一次成功匹配之后,发现无法找到一个可以和正则表达式匹配的串,于是继续匹配,一直到找到了第一个可以匹配的串 "aaab"才结束。
7. 选择(Alternation),分组(Grouping),引用(References)
|,选择,匹配该符号左边或者是右边的子表达式,比如 /java|script/ 可以匹配"java"也可以匹配“script”,注意,选择匹配只要左边匹配成功的就不会再进行右边的匹配了。
(),组合,把括号类的表达式看成一个独立的单元,使之可以使用*,+,?,|等等,主要的组合可可以被引用;(?:),也是组合的一种形式,但是这样的组合不能被引用。
\1,\2等,表示引用,\后的数字为组号。组号是从左到右分配的,也就是最左边的一个括号开始是第一组,这样分配下去。\n将匹配第n组在第一次匹配成功的字符串。比如:
/(a*b)\1/ 可以匹配 aabaab,但不能匹配 aabab。更加复杂一些的情况:
/(abc(de))\1\2/ 匹配 "abcdeabcdede"。另外不能在[]中使用引用,例如 /(a*b)[\1]/ 非法
8. ^和$,^匹配字符串的开始或者是一行的开始(在多行模式下),$匹配字符串的结束或者是一行的结束(在多行模式下),例如:
/a*b/ 匹配 "aaabaab"
/^a*b$/ 不匹配 "aaabaab"
9.标志(Flags)
标志相对前面来说是一个简单的知识点,假如我们希望匹配含有 javascript 或者 JavaScript 的字符串,我们可以使用 /[jJ]ava[sS]cript/ ,还有一种方法,就是使用标志,即 /javascript/i ,i表示进行大小写不敏感的匹配。另外还有2个标志,g,m。
g表示进行全局匹配,也就是找出所有可以匹配的串,而不会因为找到一个就停止下来。
m多行模式,影响^,$的匹配,使^匹配每行的开始,$匹配每行的结束。
这3个标志可以一起使用,也可以单独使用,比如 /abc/gi /abc/mi /abc/gmi
4) 在 JavaScript 中使用正则表达式
从理论走到实践是一个艰苦的过程,终于可以开始让人兴奋的应用了。
再论构建 RegExp对象,我们可以通过正则表达式字面值(literals)来构建一个RegExp对象:
re = /\bjava\b/
同样可以使用构造函数 re = new RegExp("\\bjava\\b");,可以看到不同,首先传递的字符串不需要 "/",其次,里面的 \ 需要转义。这是可以理解的,因为如果没有了来转义,结果就是"\bjava\b",而 \b 在字符串里面是退格符。
a. String中的方法
1.search(),接受一个String或者是一个RegExp对象,假如是String则先调用RegExp的构造函数,转化成为RegExp对象。方法返回字符串中第一次匹配成功的位置,因此g标志就没有含义了。例如:
程序代码
re = /killercat/i
str = "I am Killercat"
document.write(str.search(re))
结果:5
2.replace(),有2个参数,第一个为正则表达式或字符串,第二个为要替换的字符串。例如:
程序代码
re = /killercat/ig
str = "I am Killercat killercat"
document.write(str.replace(re,"cat")+"<br />")
document.write(str)
结果:
I am cat cat
I am Killercat killercat
解析:
1) 假如第一个参数为字符串,不会转化成为正则表达式,而是查找这个字符串。
2) 不会改变原字符串的值,而是返回一个新的字符串
3) 可以使用g,进行全局匹配
3. match(),参数和search一样,可以是字符串也可以是RegExp对象,String会被转化成为RegExp对象,但是match支持g标志,同时match返回一个数组,例如:(注意,本结果是在firefox2.0下得到的)
程序代码
re1 = /a*?b/g
re2 = /a*b/g
str = "aaabaab"
arr = str.match(re1)
for(ele in arr){
document.write(arr[ele]+"<br />")
}
document.write("next...<br />");
arr = str.match(re2)
for(ele in arr){
document.write(arr[ele]+"<br />")
}
结果:
aaab
aab
next...
aaab
aab
4. split(),参数为一个字符串或者一个正则表达式,这个参数作为字符串的分割符,返回分割的子串组成的数组,例如:
程序代码
re1 = /\s+/
str = "123 456 789"
arr = str.split(" ");
for(var ele in arr){
document.write(arr[ele]+"<br />")
}
document.write("next...<br />");
str = "123 456 789"
arr = str.split(re1);
for(ele in arr){
document.write(arr[ele]+"<br />")
}
结果:
123
456
789
next...
123
456
789
b. RegExp对象的方法
1. test(),参数是一个字符串,出现一次匹配则返回true,否则为false
程序代码
re = /a*?b/
str = "aaabaab"
document.write(re.test(str));
结果为:true