参考博文:http://www.cnblogs.com/tugenhua0707/p/5037811.html
1.基本语法
1)直接量语法
/pattern/attributes;
2)创建RegExp对象实例
new RegExp(pattern,attributes);
pattern:string 指定了正则表达式的模式
attributes: g,i 区分大小写匹配 多行匹配
@return返回值 :一个新的RegExp对象,具有指定的模式和标志
2.基本方法-字符串相关方法
1)search()方法
用于检索字符串中指定的子字符串或者检索与正则表达式相匹配的字符串
基本语法:stringObject.search(regexp);
参数regexp:可以是需要在stringObject中检索的字符串,也可以是需要检索的RegExp对象
@return返回值:stringObject中第一个与regexp对象相匹配的子串的起始位置。如果没有找到任何匹配的子串,则返回-1
注意:search()方法不执行全局匹配,它将忽略标志g,同时它也没有regexp对象的lastIndex的属性,且总是从字符串开始位置进行查找,总是返回的是stringObject匹配的第一个位置。
demo代码
var str = "hello world,hello world";
console.log(str.search(/hello/)); // 0 返回匹配到的第一个位置(使用regexp对象检索)
console.log(str.search(/hello/g)); // 0 没有全局的概念
console.log(str.search(/world/)); // 6
console.log(str.search('wo')); // 6 参数可以是字符串格式的
console.log(str.search('shifeng')); //-1 没有检索到 返回值为-1
2)match()方法
该方法用于在字符串内检索指定的值,或找到一个或者多个正则表达式的匹配。该方法类似于indexOf()或者lastIndexOf(); 但是它返回的是指定的值,而不是字符串的位置;
基本语法:stringObject.match(searchValue)或者stringObject.match(regexp)
参数:searchValue(需要检索字符串的值)
regexp(需要匹配模式的RegExp对象)
@return返回值:存放匹配成功的数组;它可以全局匹配模式,全局匹配的话,它返回的是一个数组。如果没有找到任何的一个匹配,那么它将返回的是null;返回的数组内有三个元素,第一个元素的存放的是匹配的文本,还有两个对象属性;index属性表明的是匹配文本的起始字符在stringObject中的位置;input属性声明的是对stringObject对象的引用;
demo代码
var str = "hello world";
console.log(str.match("hello"));//["hello", index: 0, input: "hello world"]
console.log(str.match("Hello"));//null
console.log(str.match(/hello/));//["hello", index: 0, input: "hello world"]
//全局匹配
var str2="1 plus 2 equal 3"
console.log(str2.match(/\d+/g));//["1", "2", "3"]
3)replace()方法
该方法用于在字符串中使用一些字符替换另一些字符,或者替换一个与正则表达式的子字符串;
基本语法:stringObject.replace(regexp/substr,replacement);
参数regexp/substr:字符串或者需要替换模式的RegExp对象
replacement:一个字符串的值,被替换的文本或者生成替换文本的函数
@return返回值:返回替换后的心字符串
注意:字符串的stringObject的replace()方法执行的是查找和替换操作,替换的模式有2种,既可以是字符串,也可以是正则匹配模式,如果是正则匹配模式的话,那么它可以加修饰符g,代表全局替换,否则的话,它只替换第一个匹配的字符串;
replacement既可以是字符串,也可以是函数,如果它是字符串的话,那么匹配的将与字符串替换,replacement的$有具体的含义
demo代码
var str = "hello world";
var s1 = str.replace('hello','a') // 替换字符串
console.log(s1);
var s2 = str.replace(/hel*o/,'b') // 使用正则替换字符串
console.log(s2);
var s3 = str.replace(/l/g,'c') // 使用正则全局替换 字符串
console.log(s3);
// $1,$2 代表的是第一个和第二个子表达式相匹配的文本
// 子表达式需要使用小括号括起来,代表的含义是分组
var name = "longen,yunxi";
var s4 = name.replace(/(\w+)\s*,\s*(\w+)/,"$2 $1");
console.log(s4); // "yunxi,longen"
// $& 是与RegExp相匹配的子字符串
var name = 'hello I am a chinese people';
var regexp = /am/g;
if(regexp.test(name)){
// 返回正则表达式匹配子串的文本
console.log(RegExp['$&']);
// 返回正则表达式匹配子串右侧的文本
console.log(RegExp["$'"]);
// 返回正则表达式匹配子串左侧的文本
console.log(RegExp["$`"]);
// 返回任何正则表达式查找过程中最后括号的子匹配
console.log(RegExp["$+"]);
// 返回任何正则表达式搜索过程中的最后匹配的字符
console.log(RegExp["$_"]);
}
/** 如下函数,回调函数参数一共有四个
* 第一个参数的含义是 匹配的字符串
* 第二个参数的含义是 正则表达式分组内容,没有分组的话,就没有该参数,
* 如果没有该参数的话那么第四个参数就是undefined
* 第三个参数的含义是 匹配项在字符串中的索引index
* 第四个参数的含义是 原字符串*/
name2.replace(/(\d+)/g,function(a,b,c,d){
console.log(a);
console.log(b);
console.log(c);
console.log(d);
});
/** 如上会执行四次,值分别如下(正则使用小括号,代表分组):
* 第一次: 123,123,0,123sdasadsr44565dffghg987gff33234
* 第二次: 44565,44565,11,123sdasadsr44565dffghg987gff33234
* 第三次: 987,987,22,123sdasadsr44565dffghg987gff33234
* 第四次: 33234,33234,28,123sdasadsr44565dffghg987gff33234*/
4)split()方法
该方法把一个字符串分割成字符串数组
基本语法:stringObject.split(separator,howmany);
参数:1、separator[必填项],字符串或者正则表达式,该参数指定的地方分割stringObject;
2、howmany[可选] 该参数指定返回的数组的最大长度,如果设置了该参数,返回的子字符串不会多于参数指定的数组。如果没有设置该参数的话,整个字符串都会被分割,不考虑它的长度。
@return返回值:一个字符串数组。该数组通过在separator指定的边界处将字符串stringObject分割成子字符串。
demo代码
var str = "what are you dong?";
console.log(str.split(" "));
console.log(str.split(""));
console.log(str.split("",3));
3.基本方法-RegExp对象方法
1)test()方法
该方法用于检测一个字符串是否匹配某个模式
基本语法:RegExpObject.test(str);
参数:str是需要检测的字符串
@return返回值:如果字符串str中含有与RegExpObject匹配的文本的话,返回true,否则返回false;
demo 代码
var str = "longen and yunxi";
console.log(/longen/.test(str)); // true
console.log(/longlong/.test(str)); //false
var regexp = new RegExp("longen");
console.log(regexp.test(str)); // true
2)exec()方法
该方法用于检测字符串中的正则表达式的匹配
基本语法:RegExpObject.exec(string)
参数:string[必填项] 要检索的字符串
@return返回值:返回一个数组,存放匹配的结果,如果未找到匹配,则返回值为null
注意:该返回的数组的第一个元素是与正则表达式相匹配的文本,该方法还返回2个属性,index属性声明的是匹配文本的第一个字符的位置;input属性则存放的是被检索的字符串string;该方法如果不是全局的话,返回的数组与match()方法返回的数组是相同的。
demo代码
var str = "longen and yunxi";
console.log(/longen/.exec(str));/
/打印 ["longen", index: 0, input: "longen and yunxi"]
//假如没有找到的话,则返回null
console.log(/wo/.exec(str));//null
4、了解正则表达式常用的概念.
1)了解正则中的普通字符
字母,数字,汉字,下划线及一些没有特殊定义的标点符号,都属于普通字符,正则中的普通字符,在匹配字符串的时候,匹配与之相同的字符即可~ 比如如下代码:
var str = "abcde";
console.log(str.match(/a/)); // ["a",index:0,input:'abcde'];
2)了解正则中的方括号[]的含义
方括号包含一系列字符,能够匹配其中任意一个字符,如[abc]可以匹配abc中任意一个字符,使用[^abc]包含的字符abc,则能够匹配abc字符之外的任何一个字符,只能是一个字符。
[abc]:查找在方括号中的任意一个字符
[^abc]:查找不在方括号中的任意一个字符
[0-9]:查找0-9中的任意一个数字
[a-z]:查找从小写a到z中的任意一个字符
(red|blue|green):查找小括号中的任意一项,小括号中的 |是或者的意思
3)理解javascript中的元字符
4)RegExp特殊字符中的需要转义字符
需要转义的特殊字符前面加 \
$:匹配字符串的结尾位置 \$
^:匹配字符串的开始位置 \^
*:匹配前面的子表达式的零次或者多次 \*
+:匹配子表达式的1次或者多次 \+
.:匹配除换行符之外的任何一个字符 \.
[:匹配一个中括号开始 \[
?:匹配前面的子表达式的零次或者1次,或指明一个非贪婪限定符 \?
\: 匹配本身的话 \\
{:标记限定符开始的地方 \{
|:指明多项中的一个选择 可以理解为或的意思 \|
5)了解量词
n+ :匹配任何至少包含一个n的字符串
n*:匹配零个或者多个n的字符串
n?:匹配零个或者1个n的字符串
n{x}:匹配包含x个n的序列字符串
n{x,y}:匹配至少x个,最多y个n的字符串
n{x,}:匹配至少x个的字符串
n$:匹配以n结尾的字符串
^n:匹配以n开头的字符串
?=n:匹配其后紧接指定的n字符串
?!n:匹配其后没有紧接指定的n字符串
6)贪婪模式 与 非贪婪模式讲解
Javascript中的正则贪婪与非贪婪模式的区别是:被量词修饰的子表达式的匹配行为;贪婪模式在整个表达式匹配成功的情况下尽可能多的匹配;非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配;
常见的修饰贪婪模式的量词
{x,y},{x,},?,*和+
常见的非贪婪模式在其后面加上一个?
{x,y}?,{x,}?,??,*?和+?
<1>贪婪模式
var str = "longen<p>我是中国人</p>yunxi<p>我是男人</p>boyboy";
//贪婪模式 匹配所有字符
console.log(str.match(/.*<\/p>/)[0]);
//后面加问号,变成非贪婪模式
console.log(str.match(/.*?<\/p>/)[0]);
7)理解正则表达式匹配原理
<1>占有字符和零宽度
在正则表达式匹配的过程中,如果子表达式匹配到的是字符内容,而非位置的话,并被保存在匹配的结果当中,那么就认为该子表达式是占有字符的;如果子表达式匹配的仅仅是位置,或者说匹配中的内容不保存到匹配的结果当中,那么就认为该子表达式是零宽度的。我们先来理解下零宽度的列子,最常见的就是环视~ 它只匹配位置;比如顺序环视;环视待会就讲;
正则匹配方式 /abc/
匹配过程:首先由字符a取得控制权,从位置0开始进行匹配,a匹配a,匹配成功;接着往下匹配,把控制权交给b,那么现在从位置1开始,往下匹配,匹配到字符串b,匹配成功,接着继续往下匹配,位置是从2开始,把控制权交给c,继续往下匹配,匹配到字符串c,匹配成功,所以整个表达式匹配成功;匹配结果为 abc 匹配的开始位置为0,结束位置为3;
含有匹配优先量词的匹配过程
如下:
源字符串abc,正则表达式为ab?c ;量词?可以理解为匹配优先量词,在可匹配可不匹配的时候,会优先选择匹配;当匹配不到的时候,再进行不匹配。先匹配b是否存在,如果不存在的话,就不匹配b;因此结果可以匹配的有 abc,ac等
匹配过程:
首先由字符a取得控制权,从位置0开始匹配,a匹配到字符串a,匹配成功;接着继续匹配,把控制权交给b,b现在就从位置1开始匹配;匹配到字符串b,匹配成功;接着就把控制权交给c,c从位置2开始继续匹配,匹配字符串c,匹配成功;整个表达式匹配成功;假如b那会儿匹配不成功的话,它会忽略b,继续匹配字符串c,也就是如果匹配成功的话,结果是ac;
因此abc匹配字符串abc,匹配的位置从0开始,到3结束。
如果匹配的结果为ac的话,那么匹配的位置从0开始,到2结束;
假如我们把字符串改为abd,或者abe等其他的,那么当匹配到最后一个字符的时候,就匹配失败;
含有忽略优先量词的匹配过程
量词?? 含义是 忽略优先量词,在可匹配和可不匹配的时候,会选择不匹配,这里的量词是修饰b字符的,所以b?? 是一个整体的。匹配过程如下
首先由字符a取得控制权,从位置0开始匹配,有”a”匹配a,匹配成功,控制权交给b?? ;首先先不匹配b,控制权交给c,由c来匹配b,匹配失败,此时会进行回溯,由b??来进行匹配b,匹配成功,然后会再把控制权交给c,c匹配c,匹配成功,因此整个表达式都匹配成功;
<2> 理解正则表达式——环视
环视只进行子表达式匹配,不占有字符,匹配到的内容不保存到最终的匹配的结果,是零宽度的,它匹配的结果就是一个位置;环视的作用相当于对所在的位置加了一个附加条件,只有满足了这个条件,环视子表达式才能匹配成功。环视有顺序和逆序2种,顺序和逆序又分为肯定和否定,因此共加起来有四种;但是javascript中只支持顺序环视,因此我们这边来介绍顺序环视的匹配过程;
如下说明:
1. (?=Expression):
顺序肯定环视,含义是所在的位置右侧位置能够匹配到regexp.
2. (?!Expression)
顺序否定环视,含义是所在的位置右侧位置不能匹配到regexp
顺序肯定环视
先看如下图:
环视只进行子表达式匹配,不占有字符,匹配到的内容不保存到最终的匹配的结果,是零宽度的,它匹配的结果就是一个位置;环视的作用相当于对所在的位置加了一个附加条件,只有满足了这个条件,环视子表达式才能匹配成功。环视有顺序和逆序2种,顺序和逆序又分为肯定和否定,因此共加起来有四种;但是javascript中只支持顺序环视,因此我们这边来介绍顺序环视的匹配过程;
如下说明:
1. (?=Expression):
顺序肯定环视,含义是所在的位置右侧位置能够匹配到regexp.
2. (?!Expression)
顺序否定环视,含义是所在的位置右侧位置不能匹配到regexp
顺序肯定环视
先看如下图:
源字符串:aa<p>one</p>bb<div>two</div>cc
正则:<(?!/?p\b)[^>]+>
正则的含义是:匹配除
之外的其余标签;
如下图:
匹配过程如下:
首先由”<” 取得控制权,从位置0开始匹配,第一个位置和第二个位置都是字符a,因此匹配失败~ 接着从位置2匹配,匹配到<, 匹配成功了,现在控制权就交给(?!/?p\b);?!是顺序否定环视,只匹配一个位置,不匹配字符,这个先不用管,首先是 /? 取得控制权,它的含义是:可匹配/,或者不匹配/, 接着往下匹配的是p字符,匹配失败,进行回溯,不匹配,那么控制权就到一位了p字符,p匹配p,匹配成功,控制权就交给\b; \b的含义是匹配单词的边界符,\b就匹配到了 > ,结果就是匹配成功,子表达式匹配就完成了;/?p\b 就匹配成功了;所以(?!/?p\b) 这个就匹配失败了;从而使表达式匹配失败;我们继续往下匹配,从b字符开始,和上面一样匹配失败,当位置是从14开始的时候 < 字符匹配到”<”,匹配成功,把控制权又交给了(?!/?p\b), 还是/?取得控制权,和上面匹配的逻辑一样,最后?p\b匹配失败了,但是(?!/?p\b) 就匹配成功了,因此这一次表达式匹配成功;如下代码匹配:
var str = "aa<p>one</p>bb<div>two</div>cc";
// 匹配的结果为div,位置从14开始 19结束
console.log(str.match(/<(?!\/?p\b)[^>]+>/)[0]);
<2> 理解正则表达式——捕获组
捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显示命名的组里,方便后面使用;可以在正则表达式内部使用,也可以在外部使用;
捕获组有2种,一种是捕获性分组,另一种是 非捕获性分组;
我们先来看看捕获性的分组语法如下:
捕获组分组语法:(Expression)
我们都知道中括号是表示范围内选择,大括号表示重复次数,小括号的含义是允许重复多个字符;
捕获性分组的编号规则:编号是按照”(”出现的顺序,从左到右,从1开始进行编号;
比如如下代码:
// 分组的列子
console.log(/(longen){2}/.test("longen")); // false
console.log(/(longen){2}/.test("longenlongen")); //true
// 分组的运用 RegExp.$1 获取小括号的分组
var str = 11122;
/(\d+)/.test(str);
console.log(RegExp.$1); // 11122
// 使用replace替换 使用分组 把内容替换
var num = "11 22";
var n = num.replace(/(\d+)\s*(\d+)/,"$2 $1");
console.log(n); // 22 11
反向引用
反向引用
反向引用标识由正则表达式中的匹配组捕获的子字符串。每个反向引用都由一个编号或名称来标识;并通过 ”\编号” 表示法来进行引用;
//反向引用console.log(/(longen)\1/.test("longen"));//falseconsole.log(/(longen)\1/.test("longenlongen"));//true
理解非捕获性分组
并不是所有分组都能创建反向引用,有一种分组叫做非捕获性分组,它不能创建反向引用,要创建一个非捕获性分组,只要在分组的左括号的后面紧跟一个问号与冒号就ok;非捕获分组的含义我们可以理解为如下:子表达式可以作为被整体修饰但是子表达式匹配的结果不会被存储;如下:
// 非捕获性分组
var num2 = "11 22"
/#(?:\d+)/.test(num2);
console.log(RegExp.$1);
//""我们再来看下使用 非捕获性分组来把页面上的所有标签都去掉,如下代码:
// 把页面上所有的标签都移除掉
var html = "<p><a href='http://baidu.com'>我来测试下</a>by<em>龙恩</em></p>";
var text = html.replace(/<(?:.|\s)*?>/g, ""); console.log(text); // 我来测试下by 龙恩
如上:我们来分析下:正则/<(?:.|\s)*?>/g 的含义是:g是修饰符,全局匹配的含义;使用非捕获性分组?: 的含义是 子表达式可以作为被整体修饰但是子表达式匹配的结果不会被存储;因此:正则/<(?:.|\s)*?>/g 的含义变为:匹配以< 开头 及 > 结束的所有字符;(?:.|\s)*? 含义是:. 代表任意字符,| 含义是或者的意思,\s 是匹配空格的意思;*号修饰符的含义是零个或者多个的意思;后面的?(问号)代表可匹配,可不匹配的含义;优先是可匹配;总起来的意思是:全局匹配字符串html 中的 以<开头 以>结尾的所有字符 替换成 空字符串,因此留下来就是文本;当然我们使用捕获性分组也可以得到同样的结果~
反向引用详细讲解
捕获性分组取到的内容,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就叫做反向引用。
反向引用的作用是:是用来查找或限定重复,查找或限定指定标识配对出现等。
捕获性分组的反向引用的写法如:\number
Number是十进制数字,即捕获组的编号。
反向引用的匹配原理
捕获分组在匹配成功时,会将子表达式匹配到的内容,保存到内存中一个以数字编号的组里,可以简单的认为是对一个局部变量进行了赋值,这时就可以通过反向引用,引用这个局部变量的值。一个捕获分组在匹配成功之前,它的内容可以是不确定的,一旦匹配成功了,它的内容就确定了,反向引用的内容也就确定了。
比如如下代码:
var str = "longenaabcd";
console.log(str.match(/([ab])\1/)[0]);//aa
代码分析:对于如上代码中的正则 /([ab])\1/, 捕获组中子表达式[ab];可以匹配a,也可以匹配b,但是如果匹配成功的话,那么它的反向引用也就确定了,如果捕获分组匹配到的是a,那么它的反向引用就只能匹配a,如果捕获分组匹配到的是b,那么它的反向引用就只能匹配到b;\1的含义是 捕获分组匹配到是什么,那么它必须与捕获分组到是相同的字符;也就是说 只能匹配到aa或者bb才能匹配成功;
该正则匹配的过程我们可以来分析下:
字符串匹配正则/([ab])\1/, 在位置0处开始匹配,0处字符是l,很明显不满足,把控制权就交给下一个字符,一直到第6个字符,才匹配到a,匹配成功,把控制权交给\1, 也就是反向引用和分组中是相同的字符,因此也匹配a,字符串中下一个字符也是a,因此匹配成功,因此整个表达式找到匹配的字符,匹配的位置开始于6,结束与8;我们再可以匹配b,原理和上面一样,这里就不再多解释了;
4.正则表达式实战
1)匹配数字结尾的
正则:/\d+$/g;
2)去掉空格
正则:str.replce(/\s/g,'');
3)判断是否由是数字或者字符串是否由数字组成
正则:/\D/g.test(str);
4)电话号码正则
正则:/^\d{3,4}-/d{7,8}/
5)手机号
正则:/(^1[3|4|5|7|8][0-9]{9}$)/
6)删除字符串左右空格
正则:str.replace(/^s+|s+$/g,'');
7)限制文本框只能输入数字和小数点(二位小数点)
正则:/^\d+\.?\d{0,2}$/
8)替换小数点前面的内容为指定内容