js笔记:js正则表达式语法(es5)

来源:互联网 发布:广州软件测试招聘 编辑:程序博客网 时间:2024/06/05 18:52
一.什么是正则表达式
正则表达式(regular expression)是一种模型,用于表示某种状态(或者说某种形式比较贴切)的字符串,可以说正则表达式里面的内容就是一系列的条件,使用正则就是对这些条件的匹配问题


二.那么如何创建正则?又如何使用正则来对字符串进行匹配呢?
在es5语法中,有两种创建正则的方法:通过new运算符来创建,或者通过直接赋值的方式进行创建(也就是我们所说的字面量形式)


new运算符(有两种形式):
var test=new RegExp('test');
或者
var test=new RegExp('test','ig');
其原理是通过new RegExp()创建一个正则对象,该构造函数有两个参数,其中第一个参数为必选(定义匹配内容或者说是匹配的模式),第二个参数为可选参数(用来定义模式修饰符)。
模式修饰符可以填写以下内容:(可以填写多个,如上示例)
i:忽略大小写;
g:全局匹配;
m:多行匹配。


直接赋值(字面量形式):
var test=/test/;
或者
var test=/test/ig;
(跟上面一样,也可以添加模式修饰符)


接下来就是如何运用正则:
首先提到的是正则对象的两个方法:test(str)与exec(str)。
test(str)(其中的str参数表示用来与该正则表达式进行匹配的字符串)方法:在字符串中查找是否存在与该正则相匹配的字符串,如果存在则返回true,不存在则返回false;
exec(str):用于在字符串中查找匹配的字段,如果执行成功,则返回该查找字符串的相关信息数组,反之则返回null。这句话可能稍微有些难理解,这里给出w3school官网中的说明:
exec() 方法的功能非常强大,它是一个通用的方法,而且使用起来也比 test() 方法以及支持正则表达式的 String 对象的方法更为复杂。
如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。此数组的第 0 个元素是与正则表达式相匹配的文本,第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),以此类推。除了数组元素和 length 属性之外,exec() 方法还返回两个属性。index 属性声明的是匹配文本的第一个字符的位置。input 属性则存放的是被检索的字符串 string。我们可以看得出,在调用非全局的 RegExp 对象的 exec() 方法时,返回的数组与调用方法 String.match() 返回的数组是相同的。
但是,当 RegExpObject 是一个全局正则表达式时,exec() 的行为就稍微复杂一些。它会在 RegExpObject 的 lastIndex 属性指定的字符处开始检索字符串 string。当 exec() 找到了与表达式相匹配的文本时,在匹配后,它将把 RegExpObject 的 lastIndex 属性设置为匹配文本的最后一个字符的下一个位置。这就是说,您可以通过反复调用 exec() 方法来遍历字符串中的所有匹配文本。当 exec() 再也找不到匹配的文本时,它将返回 null,并把 lastIndex 属性重置为 0。


看这些仍然不不是很清晰,还是回归一只程序猿慢慢一个一个尝试吧。。。
这里,我们以字面量的形式来创建正则对象吧:
比如:1.test方法示例
  var pattern=/test/i;
  var str='this is a little test!';
  alert(pattern.test(str));


  其结果为true,如果我们将str改为'this is a little Test!',同样会返回true(由于设置的模式修饰符为i:忽略大小写);
  注:模式修饰符不做任何影响,该方法只判断字符串中是否存在匹配。
2.exec方法示例(同样模式修饰符不做任何影响,该方法只判断字符串中是否存在匹配。)
  var pattern=/test/i;
  var str='this is a little test!';
  alert(pattern.exec(str));


  结果返回的是一个数组,其只有一项


  var pattern=/(a)test(b)/i;
  var str='this is a little atestb!';
  alert(pattern.exec(str));


  这里返回的是atestb,a,b(其中atestbshi与该正则匹配,a则与正则中内容为a的分组匹配,b则与正则中内容为b的分组匹配)
  现在再看上面exec方法的说明就很清晰了(正则中用括号括起来的内容就是分组)


同样的,String也有类似的对正则进行匹配的方法:
1.match(pattern):返回pattern中的子串或null;
var pattern = /test/ig; //全局搜索
var str = 'This is a test!,That is a test too';
alert(str.match(pattern)); //匹配到两个 test,test
alert(str.match(pattern).length); //获取数组的长度
注:模式修饰符必须有g,即全局匹配,才能获取所有的匹配项,如果没有设置全局g的话,则会获取分组,如果有的话


比如:
var pattern = /tes(t)/i;
var str = 'This is a test!,That is a test too';
alert(str.match(pattern)); //返回test,t
alert(str.match(pattern).length); //获取数组的长度



2.replace(pattern,replacement):用replacement将匹配pattern的字段替换;
var pattern = /test/ig;
var str = 'This is a test!,That is a test too';
alert(str.replace(pattern, 'task')); //将Box替换成了task
注:模式修饰符必须有g,即全局匹配,才能替换所有的匹配项


3.search(pattern):返回字符串中pattern开始的位置;
var pattern = /test/ig;
var str = 'This is a test!,That is a test too';
alert(str.search(pattern)); //查找到返回位置,否则返回-1
注:其无关乎是否全局匹配,只要找到即返回位置,没有则返回-1


4.split(pattern):将字符串以pattern拆分单位,并返回一个数组,该数组以拆分后的各字段组成;
var pattern = / /ig;
var str = 'This is a test!,That is a test too';
alert(str.split(pattern)); //将空格拆开分组成数组
注:无关全局换行


三.正则对象的基本属性
RegExp对象的静态属性:(即可以用RegExp直接调用的属性)
1.input(亦可用$_来代替):当前被匹配的字符串;
2.lastMatch($&):最后一个匹配字符串;
3.lastParen($+):最后一对圆括号内的匹配子串;
4.leftContext($`):最后一次匹配前的子串
5.rightContext($'):在上次匹配之后的子串;


例如:
var pattern = /(g)oogle/;
var str = 'This is google!';
pattern.test(str);//执行一下
alert(RegExp.input);//This is google!
alert(RegExp.leftContext);//This is 
alert(RegExp.rightContext);//!
alert(RegExp.lastMatch);//google
alert(RegExp.lastParen);//g
alert(RegExp.multiline);//false




RegExp对象实例属性:
1.global:Boolean值,表示是否设置全局g;
2.ignoreCase:Boolean值,表示是否设置忽略大小写i;
3.lastIndex:整数,代表下次匹配将从哪里开始;
4.multiline:Boolean值,表示是否设置多行匹配m;
5.source:正则表达式的源字符串形式;


例如:
//使用实例属性
var pattern = /google/ig;
alert(pattern.global);//true,是否全局了
alert(pattern.ignoreCase);//true,是否忽略大小写
alert(pattern.multiline);//false,是否支持换行
alert(pattern.lastIndex);//0,下次的匹配位置
alert(pattern.source);//google,正则表达式的源字符串


var pattern = /google/g;
var str = 'google google google';
pattern.test(str);//google,匹配第一次
alert(pattern.lastIndex);//6,第二次匹配的位


注:lastIndex可手动设置



四.获取控制

RegExp有很多种富有特定含义的字符用于模式匹配。
1.方括号[]
我们可以通过在方括号中填写字符来规范用于匹配的内容,比如说:
[abc]:匹配a、b、c中任意一字符,即匹配的字符为方括号其中一字符即匹配成功。
我们可以这样想,其实[]定义的就是一个集合,匹配是否成功就是看匹配字段是否包含于此集合。
具体用法如下:
[abc]查找方括号之间的任何字符。
[^abc] 查找任何不在方括号之间的字符。
[0-9] 查找任何从 0 至 9 的数字。
[a-z] 查找任何从小写 a 到小写 z 的字符。
[A-Z] 查找任何从大写 A 到大写 Z 的字符。
[A-z] 查找任何从大写 A 到小写 z 的字符。
[adgk] 查找给定集合内的任何字符。
[^adgk] 查找给定集合外的任何字符。
(red|blue|green) 查找任何指定的选项。
当然,我们也可以在括号中添加元字符。


2.元字符
即特殊含义的字符代表特定的字符集合。
.查找单个字符,除了换行和行结束符。
\w 查找单词字符。
\W 查找非单词字符。
\d 查找数字。
\D 查找非数字字符。
\s 查找空白字符。
\S 查找非空白字符。
\b 匹配单词边界。
\B 匹配非单词边界。
\0 查找 NUL 字符。
\n 查找换行符。
\f 查找换页符。
\r 查找回车符。
\t 查找制表符。
\v 查找垂直制表符。
\xxx 查找以八进制数 xxx 规定的字符。
\xdd 查找以十六进制数 dd 规定的字符。
\uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。


3.量词
即通过在相应字符后面添加特定的修饰字符以达到匹配特定数量该字符的效果,比如说a*就是指匹配0个或多个a。
n+ 匹配任何包含至少一个 n 的字符串。
n* 匹配任何包含零个或多个 n 的字符串。
n? 匹配任何包含零个或一个 n 的字符串。
n{X} 匹配包含 X 个 n 的序列的字符串。
n{X,Y} 匹配包含 X 至 Y 个 n 的序列的字符串。
n{X,} 匹配包含至少 X 个 n 的序列的字符串。
n$ 匹配任何结尾为 n 的字符串。
^n 匹配任何开头为 n 的字符串。
?=n 匹配任何其后紧接指定字符串 n 的字符串。
?!n 匹配任何其后没有紧接指定字符串 n 的字符串。


注:要注意的是,正则有两种创建方式,对于用new RegExp()的形式创建的话,这里举个例子来说:对于元字符'\w'需要写成'\\w'的形式,而对于字面量的形式我们则直接写'\w'即可。


五.贪婪和惰性
我们举个简单的例子:
var pattern = /[a-z]+/;
var str = 'abcdefjhijklmnopqrstuvwxyz';
alert(pattern.exec(str));
var result = str.replace(pattern, 'xxx');
alert(result);
结果其返回的是
abcdefjhijklmnopqrstuvwxyz
xxx
也就是说,他将str全部匹配,也就是pattern匹配的最大项,而str的每一个非空子串都能与pattern匹配,这就是贪婪。
简而言之,贪婪就是匹配的最大化。
那么,贪婪可以消除吗?当然,与之想对的就是惰性,以下是几种形式相对应的惰性模式:
+:+?
?:??
*:*?
{n}:{n}?   (这里其实构不成贪婪)
{n,}:{n,}?
{n,m}:{n,m}?



六.几种特殊的情况:
1.捕获性分组与非捕获性分组
所谓的捕获性分组就是说,所有的分组都捕获,比如下面的这种情况:
//捕获性分组和非捕获性分组
var pattern = /(\d+)([a-z])/; //捕获性分组
var str = '123abc';
alert(pattern.exec(str));
返回的是:123a,123,a


所谓的非捕获性分组就是说你可以通过在对应的分组开头填写'?:'使该分组无法捕获到,如下:
var pattern = /(\d+)(?:[a-z])/; //非捕获性分组
var str = '123abc';
alert(pattern.exec(str));
返回的是:123a,123


当然,我也可以这样写:
var pattern = /(?:\d+)([a-z])/; //非捕获性分组
var str = '123abc';
alert(pattern.exec(str));
返回的是:123a,a


3.分组嵌套
//使用分组嵌套
var pattern = /(A?(B?(C?)))/; //从外往内获取
var str = 'ABC';
alert(pattern.exec(str));
返回的是:ABC,ABC,BC,C


4.前瞻捕获
即设置一个后缀条件
//使用前瞻捕获
var pattern = /(goo(?=gle))/; //goo后面必须跟着gle才能捕获
var str = 'google';
alert(pattern.exec(str));
注:(?=gle)并非匹配字段,而是一个匹配条件