正则表达式
<!--more-->
##基本语法 regular expression是计算机科学中的一个概念。正则表达式使用单个字符串来描述匹配一系列符合某个句法规则的字符串。
###创建
- 构造函数
var reg = new RegExp('<%[^%>]+%>','g');
- 字面量
var reg = /<%[^%]%>/g;
g全文搜索,i忽略大小写,m多行搜索
###元字符
具有特殊意义的专用字符,用来规定其前导字符
( [ { \ ^ $ | ) ? * + .
不同组合中的元字符有不同的意义,举例
字符 | 含义
-- | --
\t | 水平制表符
\n | 换行符
\r | 回车符
\f | 换页符
\cX | 与x对应的控制字符(Ctrl + x)
\v | 垂直制表符
\0 | 空字符
###字符类
可以使用[]来构建一个简单的类
var reg = /[abc123]/;
创建一个单字符的类,代表这个字符可以是a,可以是b,可以是c,可以是1,...可以是3。
取反
可以使用^来进行取反,
var reg = /[^abc123]/;
代表着这个单字符可以是任何其他的单字符,除了a,b,c,1,2,3之外。
范围类
如果要匹配单个字符,让单字符只能取数字的话,可以使用字符类
写成:
var reg = /[0123456789]/;
这么写比较麻烦,所以可以使用范围类,我们可以使用x-y来连接两个字符,表示从x到y的任意字符,是个闭区间,意味着包含x和y本身,这样,我们要匹配单个数字就可以写成:
var reg2 = /[0-9]/;
要匹配所以的单个字母,可以写为
var reg3 = /[a-zA-Z]/;
预定义类
上面创建了一些类,用来表示数组,字母等。但是这么写也比较麻烦,正则表达式提供了几个常见的预定义类来匹配常见的字符
字符 | 等价类 | 含义 |
---|---|---|
. | [^\r\n] | 除了回车符和换行符之外的所有字符 |
\d | [0-9] | 数字字符 |
\D | 1 | 非数字字符 |
\s | [\t\n\x0B\f\r] | 空白符 |
\S | [^\t\n\x0B\f\r] | 非空白符 |
\w | [a-zA-Z_0-9] | 单词字符,字母,数字下划线 |
\W | 2 | 非单词字符 |
有了这些预定义类,写一些正则就比较方便了,比如我们希望匹配一个ab+数字+任意字符的字符串,就可以写作:
var reg = /ab\d./;
边界
正则表达式还提供了几个常用的边界匹配字符
字符 | 含义 |
---|---|
^ | 以xxx开头 |
$ | 以xxx结尾 |
\b | 单词边界 |
\B | 非单词边界 |
^如果不写在[]内的话,不代表取反,代表以xxx开头,例如:var reg = /hello/;
代表以hello开头,相应的也有$表示为以xxx结尾,举例说明:
var reg = /^h\dm/g;
var str = 'h3m h4m h2m';
console.log(str.match(reg));// ["h3m"] 只匹配了第一个h\dm,因为有^
var reg2 = /h\dm$/g; // $代表以xxx结尾
console.log(str.match(reg2));//["h2m"] / 只匹配了最后一个h\dm 因为有$
var reg3 = /^h\dm$/g; //代表既以h\dm开头,又以h\dm结尾的
console.log(str.match(reg3)); // null 匹配不到
//关于既有开头又有结尾的例子 比如匹配手机号 以1开头,以10个数字结尾
var phoneReg = /^1\d{10}$/; //\d{10}代表10个数字
var phoneStr = '13892229999';
console.log(phoneStr.match(phoneReg)); //"13892229999" 匹配不到返回null
单词边界
var str = 'hello worhellold hello';
var reg = /hello/g;
console.log(str.match(reg)); // ["hello", "hello", "hello"] 会将3个hello都匹配到,但是如果想要只匹配单词hello的话要使用\b
var reg2 = /\bhello/g;
console.log(str.match(reg2)); // ["hello", "hello"] 只匹配到了单词hello
var str2 = 'hello wor-hello-ld hello'; // 写成如此格式,也被识别为合法的单词
console.log(str2.match(reg2)); // ["hello", "hello", "hello"] 这么写也被识别为合法的,所以匹配到了3个hello单词
量词
之前写的方法都是一一匹配的,但是如果希望匹配一个连续出现很多次的字符,例如数字的字符串,不需要写成\d\d\d\d
,我们可以使用量词
字符 | 含义 |
---|---|
? | 出现一次或者0次(最多出现一次) |
+ | 出现一次或者多次(最少出现一次) |
* | 出现0次或者多次(任意次) |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
{,m} | 最多出现m次 |
使用举例: | |
``` | |
var reg = /[a-z]\d?/g; // ?代表最多出现一次 | |
console.log('a12345b678cde'.match(reg)); //["a1", "b6", "c", "d", "e"] 因为后面的\d? 有?存在,即最多出现一次,所以后面的cde没有数字也可以被匹配到 | |
var reg2 = /[a-z]\d+/g; | |
console.log('a12345b678cde'.match(reg2));//["a12345", "b678"],+为最少出现一次,则a,b后面的有多少都可以匹配到,cde后面没有数字所以匹配不到 | |
var reg3 = /[a-z]\d*/g; | |
console.log('a12345b678cde'.match(reg3));//["a12345", "b678", "c", "d", "e"] *代表可以有任意多次,包括0,所以都能匹配到 |
var reg4 = /[a-z]\d{4}/g; //匹配字母后面4个字符
console.log('a12345b678cde'.match(reg4));//["a1234"]
var reg5 = /[a-z]\d{1,3}/g; //匹配字母后面1-3个字符
console.log('a12345b678cde'.match(reg5)); // ["a123", "b678"] 1-3尽量多的去匹配,3个没有就2个,逐渐减小,先匹配多的
### 贪婪模式 非贪婪模式
上面提到的{n,m},如果出现多次,只要是n-m中的值都满足条件,到底是按照n还是m来匹配。 量词在默认条件下是尽可能多的匹配的,即默认贪婪模式
`var reg = /\d{3,5}/g; '123456789'.match(reg); //{"12345","6789"}`
与贪婪模式相对的,就有非贪婪模式,即尽可能少的匹配,一旦成功匹配之后不再继续尝试,在后面加上?即可
`var reg2 = /\d{3,5}?/g; '123456789'.match(reg); //{"12345","6789"}`
### 分组
上面的量词解决的是单个字符重复多次的问题,如果我们需要匹配重复的多个字符,比如匹配hello出现20次,如果写成hello{20}意味着是hell+o出现20次,o自己重复20次,而不是整个hello重复20次。
我们可以使用分组()来解决这个问题,写成:
`/(hello){20}/g;`
###或
对于上面的情况,如果我们希望匹配hello或者world出现20次,可以通过使用 | 进行或操作
`/(hello|world){20}/g;`
###前瞻
表达式 | 含义
-- | --
exp1(?=exp2) | 匹配后面是exp2的exp1
exp1(?!exp2) | 匹配后面不是exp2的exp1
举例:`good(?=Bayon)`匹配后面有Bayon的good
var reg = /good(?=Bayon)/;
reg.exec('goodBayon123'); // ['good']
reg.exec('goodCasper123'); // null
##正则表达式的一些相关方法
### RegExp.prototype.test(str)
检测字符串参数中是否存在正则表达式模式,存在返回true不存在返回false
var reg = /hello/; //用来检验字符串 匹配成功了返回true
console.log(reg.test('hello world')); //true
//具体应用举例,用来判断是否为手机号
function isPhoneNumber (str) {
if (/^1\d{10}$/g.test(str)) { //匹配到手机号时返回true
console.log('是合法的手机号码');
}
}
isPhoneNumber('13812345678');
###RegExp.prototype.exec(str)
用于正则表达式模式在字符串中运行查找,如果exec()找到了匹配的文本,则返回一个结果数组,否则返回null
除了数组元素和length属性之外,exec()方法返回对象还包括两个属性。
- index 属性声明的是匹配文本的第一个字符的位置
- input属性则存放的是被检索的字符串string
举例说明:
var str = 'hallo deejay,hbllo world,hcllo daisy'; //通过正则找到各个错误的hello
var reg = /h[a-z]llo/g;
var result = reg.exec(str);
console.log(result);//["hallo", index: 0, input: "hallo deejay,hbllo world,hcllo daisy"]
result = reg.exec(str);
console.log(result);//["hbllo", index: 13, input: "hallo deejay,hbllo world,hcllo daisy"]
result = reg.exec(str);
console.log(result);//["hcllo", index: 25, input: "hallo deejay,hbllo world,hcllo daisy"]
### String.prototype.search(reg)
search()方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。
search方法不执行全局匹配,它将忽略标志g,同时也忽略正则表达式对象的lastIndex属性,总是返回字符串的第一个匹配的位置
###String.prototype.match(reg)
match()方法将检索字符串,以找到一个或者多个与regexp匹配的文本。regexp是否有全局g标志会影响结果。
###String.prototype.replace(reg,replaceStr)
关于string对象的replace方法,一般可以传入两个字符串,但是只能replace一次,如果把第一个参数传入regexp的话,就可以是replace变得灵活。
var str = 'hallo deejay,hbllo world,hcllo daisy'; //通过正则找到各个错误的hello
var reg = /h[a-z]llo/g;
str = str.replace(reg,'hello'); // 传入的第一个参数为regexp,找到匹配的字符串替换成hello
- String.prototype.replace(reg,function)
当replace方法的第二个参数为function的时候,这个function会在每次替换的时候调用。
var str = 'hallo deejay,hbllo world,hcllo daisy'; //通过正则找到各个错误的hello
var reg = /h[a-z]llo/g;
str = str.replace(reg,function (value) {
console.log(arguments);
return value[0].toUpperCase() + value.substring(1,value.length);
})
console.log(str); //Hallo deejay,Hbllo world,Hcllo daisy
###String.prototype.split(reg)
经常使用split方法把字符串分割为字符数组
`'a,b,c,d'.split(","); // ["a","b","c","d"];`
相应的,也可以使用regexp进行切割:
`"a1b2c3".split(/\d/); // ["a","b","c","d"]`