你的位置:首页 > Java教程

[Java教程]JS正则表达式


正则表达式的构成:模式+标志

模式:即需匹配的字符串

标志:指明处理方式

    • g(应用与整个字符串)
    • i(不区分大小写)
    • m(支持多行)

正则表达式的创建:正则表达式字面量方法、RegExp构造函数方法

正则表达式字面量方法:var name = /pattern/flags;

1 var pattern1 = /at/g; //匹配字符串中所有“at” 2 var pattern2 = /[bc]at/i; //匹配第一个"bat"或"cat",不区分大小写 3 var pattern3 = /.at/gi; //匹配所有以"at"结尾的3个字符串的组合,不区分大小写

需要注意的是,如果想要匹配的字符串中包含元字符时,就必须转义

1 var pattern4 = /\[bc\]at/i; //匹配第一个"[bc]at",不区分大小写2 var pattern5 = /\.at/gi; //匹配所有的".at",不区分大小写

RegExp构造函数方法:var name = new RegExp("pattern","flags");

1 var pattern1 = new RegExp("[bc]at","i");2 //等价于3 var pattern1 = /[bc]at/i; 

 值得注意的是,相比于字面量形式,构造函数中的字符串中的元字符本身的匹配需要双重转义。例如:

 /\[bc\]at/ 等价于构造函数中的字符串为 "\\[bc\\]at" 

 元字符含义

    具有特殊意义的专用字符,如果匹配元字符本身,则需要转义。正则表达式中的元字符包括( [ { \ ^ $ | ) ? * + . ] }

     字符  含义


 

  • \    转义字符,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界。或对正则表达式功能字符的还原,如"*"匹配          它前面元字符0次或多次,/a*/将匹配a,aa,aaa,加了"\"后,/a\*/将只匹配"a*" 
  • ^     匹配一个字符串的开头,表示后面出现的字符必须出现在开头/^a/匹配"an A",而不匹配"An a"。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位              置。
  • $       匹配一个字符串的结尾,表示前面出现的字符必须出现在结尾/a$/匹配"An a",  而不匹配"an A"。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。

比如比如我们要匹配一个http://cnblogs.com形式的域名: 

1 var url = "http://cnblogs.com";2 var reUrl = /^(http):\/\/cnblogs\.(com)$/gi;3 var result =reUrl.exec(url);4 document.write(result[0]);//http://cnblogs.com

  • +       匹配前面的字符或子表达式出现1次或多次,/ba+/将匹配ba,baa,baaa
  • ?       匹配前面的字符或子表达式出现0次或1次,/ba?/将匹配b,ba
  • *       匹配前面的字符或子表达式出现0次或多次,/ba*/将匹配b,ba,baa,baaa
  • .          匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用如 '[.\n]' 的模式。
  • (x)     匹配x保存x在名为$1...$9的变量中
  • x|y    匹配x或y
  • {n}    精确匹配前一项n次,c{2}表示2个c
  • {n,}   匹配前一项n次以上
  • {n,m} 匹配前一项至少n次,但不能超过m次
  • [xyz]  字符集(character set),匹配这个集合中的任一一个字符(或元字符)
  • [^xyz]  不匹配这个集合中的任何一个字符
  • [\b]   匹配一个退格符(特例)
  • \b     匹配一个单词的边界,也就是指单词和空格间的位置。例如,'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
  • \B     匹配一个单词的非边界,'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
  • \cX   X是一个控制符,/\cM/匹配Ctrl-M
  • \d     匹配一个数字字符,/\d/ 等价于/[0-9]/
  • \D     匹配一个非字数字符,/\D/ 等价于 /[^0-9]/
  • \n     匹配一个换行符
  • \r     匹配一个回车符
  • \s     匹配一个空白字符,包括\n,\r,\f,\t,\v等
  • \S    匹配一个非空白字符,等于/[^\n\f\r\t\v]/
  • \t     匹配一个制表符
  • \v    匹配一个垂直制表符
  • \w    匹配一个单词字符(含数字),包括下划线,如[\w]匹配"$5.98"中的5,等价于[a-zA-Z0-9]
  • \W   匹配一个非单词字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]
  • \xxx 由十进制数 XXX 指 定的ASCII码字符
  • \xnn 由十六进制数 nn 指定的ASCII码字符   

  简单示例


例1:

1 var reg = /\s.+/;2 var str='This is a test String.';3 alert(reg.exec(str));

返回"is a test String.",正则的意思是匹配第一个空格以及其后的所有非换行字符。

例2:

1 var reg = /\S+/;2 var str='This is a test String.';3 alert(reg.exec(str));

匹配结果为This,当遇到第一个空格之后,正则就停止匹配了。

例3:var reg=/^\s*$/; //匹配任意空或空白字符,如果你什么也没输入,或输入的只有空格、回车、换行等字符,则匹配成功。这样就可以验证用户是否正确输入内容了。
这个用来验证输入框里是否写了有效效字符,用法如下:

1 var reg=/^\s*$/;2 if(reg.test(value)){3  alert('请输入有效值');4  return false;5 }

View Code

例4:

1 var reg = /\w+/;2 var str='zhufengpeixun';3 alert(reg.exec(str));

返回完整的zhufengpeixun字符串,因为所有字符都是单词字符。

1 var reg = /\w+/;2 var str='.className';3 alert(reg.exec(str));

结果显示匹配了字符串中的className,只有第一个“.”唯一的非单词字符没有匹配。

1 var reg = /\w+/;2 var str='正则表达式';3 alert(reg.exec(str));

试图用单词字符去匹配中文自然行不通了,返回 null

\W表示非单词字符,等效于[^a-zA-Z0-9]

1 var reg = /\W+/;2 var str='正则表达式';3 alert(reg.exec(str));

返回完整的字符串,因为,中文算作是非单词字符。 

重复匹配


以匹配一个email地址为例,mymail@mail.com这样的一个email地址必须包括一个合法的用户名mymail,@符号以及一个合法的域。其中用户名和域名的字符个数都是无法判断的,但是有一点是肯定的——用户名必须至少是一个字符,域名至少是两个字符中间还必须有一个点号。于是我们可以这样做:

1 var reMail = /w+@w+.w+/i; 2 var email = "mymail@mail.com"; document.write(reMail.test(email)); //true

“+”表示字符出现一次或多次,至少出现一次。这个正则表达式其实并不能匹配所有合法的email地址,后面我们继续完善。除了“+”可以指定至少匹配一次外,还有很多其他的可以指定匹配次数的方式。

  • ? 出现零次或一次,最多一次
  • * 出现任意次(零次、一次、多次)
  • + 出现一次或多次,至少一次
  • {n} 能且只能出现n次
  • {n,m} 至少出现n次,最多出现m次
  • {n,} 至少出现n次

www.gogle.com,www.google.com,www.gooogle.com这三个网址都能正确地打开google的首页,于是就可以用{n,m}匹配其中的1个,2个或3个字母”o”。

1 var gogle = "www.gogle.com"; 2 var google = "www.google.com"; 3 var gooogle = "www.gooogle.com";4 var reGoogle = /w{3}.go{1,3}gle.com/i; document.write(reGoogle.test(gogle)); //true document.write(reGoogle.test(google)); //true document.write(reGoogle.test(gooogle)); //true

防止过度匹配


有这样一段HTML文本:

 var html = "<em>omiga</em>for a simple life<em>http://omiga.org/</em>"; 

 如果现在要讲<em></em>及其中间的文本匹配出来,正则表达式可以这样写:

1 var reEm1 = /<em>.*</em>/gi;
2 document.write(html.match(reEm1)); //"<em>omiga</em>for a simple life<em>http://omiga.org/</em>" 3 var reEm2 = /<em>.*?</em>/gi;
4 document.write(html.match(reEm2)); //<em>omiga</em>,<em>http://omiga.org/</em>

 当使用贪婪模式的时候,”.*”会最大程度地进行字符匹配,所以输出了整个字符串。而在惰性模式中,”.*?”只进行最小限度的匹配,所以完整的输出了我们需要的字符串。

 惰性模式的语法很简单,即是在贪婪模式后面加上一个“?”即可。

  • * –> *?
  • + –> +?
  • {n,} –> {n,}?

 位置匹配


  var s = "_Don’t do it!"; 

 如何将单词“do”匹配出来?it’s easy!

 var reDo = /do/gi; document.write(s.match(reDo)); //Do,do 

 但是这个简单的正则表达式/do/gi将“don’t”中的“do”也进行了匹配,可这并不是想要的结果。而在正则表达式中有专门用来进行单词边界匹配的限定符”b“。

 var reDo = /\bdo\b/gi; document.write(s.match(reDo)); //do 

 "\b"到底匹配的什么呢?”\b”匹配的是一个位置,一个位于”\w“(字母,数字,下划线)和”\W“之间的位置。

 既然有”\b”,那有”\B”吗?当然,他和”\b“刚好相反,由来匹配一个不是单词边界的位置。比如上例中匹配”don’t”中的”do”时”\B”就可派上用场。

 var reDo = /BdoB/gi; document.write(s.match(reDo)); //Do 

 在介绍取非匹配的时候介绍^只用位于[]并紧跟[方能取非匹配,而^还有另外一种用途——字符串边界匹配。

  • ^ 用来匹配字符串开头
  • $ 用来匹配字符串结尾

 比如我们要匹配一个http://omiga.org形式的org域名:

1 var url = "http://omiga.org"; 2 var reUrl = /^(http)://omiga.(org)$/gi; document.write(reUrl.test(url)); //true

正则表达式reUrl限制url必须以”http”开头,以”org”结尾。

又如经常被扩展的string方法trim:

function trim(s){   return s.replace(/(^s*)|(s*$)/g,""); }

同时我们可以在整个模式的最前面使用(?m)来启用分行匹配模式。这样,^不但匹配正常的字符串开头,还将匹配行分隔符(换行符)后面的开始位置;$不仅匹配正常的字符串结尾,还将匹配行分隔符(换行符)后面的结束位置。

  选择、分组和分组的引用


|    选择  匹配的要么是该符号左边的子表达式,要么它右边的子表达式

(...)   分组  将几个项目分为一个单元.这个单元可由 *、+、?和|等符号使用,而且还可以记住和这个组匹配的字符以供此后引用 

\n    表示第n个分组所匹配的内容.分组是括号中的子表达式(可能是嵌套的).分组号是从左到右计数的左括号数 

例1:

1 var reg = /\w/;2 var str='zhufengpeixun';3 alert(reg.exec(str));4 //返回z。

例2:

1 var reg = /(\w)(\w)/;2 var str='zhufengpeixun';3 alert(reg.exec(str));

返回zh,z,h ,zh是整个正则匹配的内容,z是第一个括号里的子正则表达式匹配的内容,h是第二个括号匹配的内容。

例3:

1 var reg = /(\w)\1/;2 var str='zhufengpeixun';3 alert(reg.exec(str));

则会返回null。这里的“\1”就叫做反向引用,它表示的是第一个括号内的子正则表达式匹配的内容。在上面的例子中,第一个括号里的(\w)匹配了z,因此“\1”就同样表示z了,在余下的字符串里自然找不到z了。与第二个例子对比就可以发现,“\1”是等同于“第1个括号匹配的内容”,而不是“第一个括号的内容”

1 var reg = /(\w)\1/;2 var str='bbs.zhufengpeixun.cn';3 alert(reg.exec(str));

这个正则则会匹配到bb,b。同样,前面有几个子正则表达式我们就可以使用几个反向引用。例如:

1 var reg = /(\w)(\w)\2\1/;2 var str='woow';3 alert(reg.exec(str));

会匹配成功,因为第一个括号匹配到w,第二个括号匹配到o,而\2\1则表示ow,恰好匹配了字符串的最后两个字符。

括号() ,表示子表达式,也叫分组

1 var reg = /^(b|c).+/;2 var str='bbs.blueidea.com';3 alert(reg.exec(str));//返回bbs.blueidea.com,b

这个正则是为了实现只匹配以b或者c开头的字符串,一直匹配到换行字符,但是上面我们已经看到了,可以使用“\1”来反向引用这个括号里的子正则表达式所匹配的内容。而且exec方法也会将这个字正则表达式的匹配结果保存到返回的结果中。

  不记录子正则表达式的匹配结果[匹配不捕获]


 使用形如(?:pattern)的正则就可以避免保存括号内的匹配结果。例如:

1 var reg = /^(?:b|c).+/;2 var str='bbs.blueidea.com';3 alert(reg.exec(str));

可以看到返回的结果不再包括那个括号内的字正则表达式多匹配的内容。同理,反向引用也不好使了:

1 var reg = /^(b|c)\1/;2 var str='bbs.zhufengpeixun.cn';3 alert(reg.exec(str));

返回bb,b。bb是整个正则表达式匹配的内容,而b是第一个子正则表达式匹配的内容。

1 var reg = /^(?:b|c)\1/;2 var str='bbs.zhufengpeixun.cn';3 alert(reg.exec(str));

返回null。由于根本就没有记录括号内匹配的内容,自然没有办法反向引用了。

正向预查


 所谓正向预查(?=pattern),意思就是:要匹配的字符串,后面必须紧跟着pattern。

1 var reg = /cainiao(?=8)/;2 var str='cainiao8';3 alert(reg.exec(str));//cainiao

 匹配cainiao。需要注意的是,括号里的内容并不参与真正的匹配,只是检查一下后面的字符是否符合要求而已.

 形式(?!pattern)?=恰好相反,要求字符串的后面不能紧跟着某个pattern,例:

1 var reg = /zhufeng(?!js)/;2 var str=`zhufengjs`;3 alert(reg.exec(str));

 返回null,因为正则要求,zhufeng的后面不能是js

RegExp实例属性


  •  global:布尔值,若全局选项g已设置则返回true,否则返回false;
  • ignoreCase:布尔值,若忽略大小写选项i已设置则返回true,否则返回false;
  • lastIndex:整数,使用exec或test方法时被填入,表示下次匹配将会从哪个字符位置开始,从0算起;
  • multiline:布尔值,表示多行模式选项m是否设置,若设置则返回true,否则返回false;
  • source:正则表达式的元字符串形式。/\/的source将返回”\“。按照字面量形式的字符串模式返回。
1 var pattern1 = /\[bc\]at/i;2 var pattern2 = new RegExp("\\[bc\\]at","");3 alert(pattern1.source); //"\[bc\]at"4 alert(pattern2.source); //"\[bc\]at"

 RegExp方法与String方法


    在javascript中RegExp和String对象都有处理正则表达式的方法。

  • test -- RegExp的test方法用来测试字符串是否匹配给出的匹配模式,返回布尔值;
  • exec -- RegExp的exec方法返回包含第一个匹配的的数组或null;
  • match -- String的match方法返回包含所有匹配子字符串的数组;
  • replace -- String的replace方法完成string的替换操作,支持正则表达式;
  • search -- 与String的indexof方法类似,不同的是search支持正则表达式,而不仅仅是字符串;
  • split -- 按照一定规则拆分字符串并将子字符串存储到数组中的String方法。
  • toString()和toLocaleString()--返回正则表达式字面量