Home  >  Article  >  php教程  >  Teach you to easily remember JS regular expressions

Teach you to easily remember JS regular expressions

高洛峰
高洛峰Original
2016-12-26 16:48:131283browse

前言

正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

为啥要有正则表达式呢?其实就是因为计算机笨(这话不是我说的),比如123456@qq.com我们一看就是邮箱,可是计算机不认识啊,所以我们就要用一些计算机认识的语言,来制定好规则,告诉它符合这个规则的就是个邮箱,这样计算机就能帮我们找到对应的东西了。所以正则就是用来设置规则,来完成我们需求的一些操作的,比如登录验证啦,搜索指定的东西啦等等,说太多都是多余,直接看正题吧。

定义正则:

var re = new RegExp(“a”);  //RegExp对象。参数就是我们想要制定的规则。有一种情况必须用这种方式,下面会提到。
var re = /a/;   // 简写方法 推荐使用 性能更好  不能为空 不然以为是注释 ,

正则的常用方法

1  test()  :在字符串中查找符合正则的内容,若查找到返回true,反之返回false.

用法:正则.test(字符串)

例子:判断是否是数字

var str = '374829348791';
var re = /\D/;  // \D代表非数字
if( re.test(str) ){ // 返回true,代表在字符串中找到了非数字。
 alert('不全是数字');
}else{
 alert('全是数字');
}

正则表达式中有很多符号,代表着不同的意思,用来让我们去定义不同的规则,比如上面\D,还有下面的这些:

\s : 空格

\S : 非空格

\d : 数字

\D : 非数字

\w : 字符 ( 字母 ,数字,下划线_ )

\W : 非字符例子:是否有不是数字的字符

(下面会根据例子,依次讲一些常用的字符,最后再作总结。)

 2   search()  :在字符串搜索符合正则的内容,搜索到就返回出现的位置(从0开始,如果匹配的不只是一个字母,那只会返回第一个字母的位置), 如果搜索失败就返回 -1

用法:字符串.search(正则)

在字符串中查找复合正则的内容。忽略大小写:i——ignore(正则中默认是区分大小写的 如果不区分大小写的话,在正则的最后加标识 i )

例子:在字符串中找字母b,且不区分大小写

var str = 'abcdef';
 
var re = /B/i;
 
//var re = new RegExp('B','i'); 也可以这样写
 
alert( str.search(re) ); // 1

3  match()  在字符串中搜索复合规则的内容,搜索成功就返回内容,格式为数组,失败就返回null。

     用法: 字符串.match(正则)

     量词:+ 至少出现一次 匹配不确定的次数(匹配就是搜索查找的意思)

    全局匹配:g——global(正则中默认,只要搜索到复合规则的内容就会结束搜索 )

例子:找出指定格式的所有数字,如下找到 123,54,33,879

var str = 'haj123sdk54hask33dkhalsd879';
var re = /\d+/g;   // 每次匹配至少一个数字  且全局匹配  如果不是全局匹配,当找到数字123,它就会停止了。就只会弹出123.加上全局匹配,就会从开始到结束一直去搜索符合规则的。如果没有加号,匹配的结果就是1,2,3,5,4,3,3,8,7,9并不是我们想要的,有了加号,每次匹配的数字就是至少一个了。
alert( str.match(re) );   // [123,54,33,879]

4 replace() :查找符合正则的字符串,就替换成对应的字符串。返回替换后的内容。

    用法: 字符串.replace(正则,新的字符串/回调函数)(在回调函数中,第一个参数指的是每次匹配成功的字符)

     | : 或的意思 。

   例子:敏感词过滤,比如 我爱北京天安门,天安门上太阳升。------我爱*****,****上太阳升。即北京和天安门变成*号,

一开始我们可能会想到这样的方法:

var str = "我爱北京天安门,天安门上太阳升。";
var re = /北京|天安门/g; // 找到北京 或者天安门 全局匹配
var str2 = str.replace(re,'*'); 
alert(str2) //我爱**,*上太阳升 
 
//这种只是把找到的变成了一个*,并不能几个字就对应几个*。

要想实现几个字对应几个*,我们可以用回调函数实现:

var str = "我爱北京天安门,天安门上太阳升。";
var re = /北京|天安门/g;  //  找到北京 或者天安门 全局匹配
var str2 = str.replace(re,function(str){
              alert(str); //用来测试:函数的第一个参数代表每次搜索到的符合正则的字符,所以第一次str指的是北京 第二次str是天安门 第三次str是天安门
            var result = '';
            for(var i=0;i<str.length;i++){
                result += &#39;*&#39;;
            }              
            return result; //所以搜索到了几个字就返回几个* 
        });
alert(str2)  //我爱*****,***上太阳升         
//整个过程就是,找到北京,替换成了两个*,找到天安门替换成了3个*,找到天安门替换成3个*。

replace是一个很有用的方法,经常会用到。

正则中的字符

():,小括号,叫做分组符。就相当于数学里面的括号。如下:

var str = &#39;2013-6-7&#39;;
var re1 = /\d-+/g;  // 全局匹配数字,横杠,横杠数量至少为1,匹配结果为:  3- 6-
var re1 = /(\d-)+/g;  // 全局匹配数字,横杠,数字和横杠整体数量至少为1   3-6-
var re2  = /(\d+)(-)/g;   //  全局匹配至少一个数字,匹配一个横杠 匹配结果:2013- 6-

同时,正则中的每一个带小括号的项,都叫做这个正则的子项。子项在某些时候非常的有用,比如我们来看一个栗子。

例子:让2013-6-7 变成 2013.6.7

var str = &#39;2013-6-7&#39;;
var re = /(\d+)(-)/g;
str = str.replace(re,function($0,$1,$2){
    
       //replace()中如果有子项,
      //第一个参数:$0(匹配成功后的整体结果  2013-  6-),
         // 第二个参数 : $1(匹配成功的第一个分组,这里指的是\d   2013, 6)
        //第三个参数 : $1(匹配成功的第二个分组,这里指的是-    - - )   
    return $1 + &#39;.&#39;;  //分别返回2013.   6.
    
});
alert( str );   //2013.6.7
//整个过程就是利用子项把2013- 6- 分别替换成了2013. 6.  最终弹出2013.6.7

match方法也会返回自己的子项,如下:

var str = &#39;abc&#39;;
var re = /(a)(b)(c)/;
alert( str.match(re) );  //[abc,a,b,c]( 返回的是匹配结果 以及每个子项  当match不加g的时候才可以获取到子项的集合)

补充:exec()方法:和match方法一样,搜索符合规则的内容,并返回内容,格式为数组。

                      用法:正则.exec(字符串);

属性:input(代表要匹配的字符串) 

栗子:不是全局匹配的情况:

 var testStr = "now test001 test002";   
 var re = /test(\d+)/; //只匹配一次     
 var r = "";   
 var r = re.exec(testStr)
  alert(r);// test001  001 返回匹配结果,以及子项
  alert(r.length); //2   返回内容的长度
  alert(r.input); //now test001 test002    代表每次匹配成功的字符串 
  alert(r[0]);   //test001   
  alert(r[1]);  //001    代表每次匹配成功字符串中的第一个子项 (\d+) 
  alert(r.index );   //  4   每次匹配成功的字符串中的第一个字符的位置

全局匹配:如果是全局匹配,可以通过while循环 找到每次匹配到的字符串,以及子项。每次匹配都接着上次的位置开始匹配

 var testStr = "now test001 test002";   
 var re = /test(\d+)/g;    
 var r = "";  
//匹配两次 每次匹配都接着上一次的位置开始匹配,一直匹配到最后r就为false,就停止匹配了 匹配到test001 test002  
while(r = re.exec(testStr)){
    alert(r);//返回每次匹配成功的字符串,以及子项,分别弹出 :test001 001,test002  002
    alert(r.input); //分别弹出:   now test001 test002    now test001 test002  
    alert(r[0]);   //代表每次匹配成功的字符串  分别弹出:  test001     test002
    alert(r[1]);  //代表每次匹配成功字符串中的第一个子项 (\d+)  分别弹出:001   002
    alert(r.index );   // 每次匹配成功的字符串中的第一个字符的位置,分别弹出:4  12
    alert(r.length); //分别弹出:2   2
}

[] : 表示某个集合中的任意一个,比如 [abc] 整体代表一个字符 匹配 a b c 中的任意一个,也可以是范围,[0-9] 范围必须从小到大 。

[^a] 整体代表一个字符   :^写在[]里面的话,就代表排除的意思

例子:匹配HTML标签 比如c49e9ffb0f4a387e7bc40de3cde1b533hahahah 16b28748ea4df4d9c2150843fecfba68 找出标签c49e9ffb0f4a387e7bc40de3cde1b53316b28748ea4df4d9c2150843fecfba68

var re = /<[^>]+>/g; //匹配左括号 中间至少一个非右括号的内容(因为标签里面还有属性等一些东西),然后匹配右括号
var re = /<[\w\W]+>/g; //匹配左括号 中间至少一个字符或者非字符的内容,然后匹配右括号
// 其实就是找到左括号,然后中间可以有至少一个内容,一直到找到右括号就代表是一个标签。

转义字符

\s : 空格

\S : 非空格

\d : 数字

\D : 非数字

\w : 字符 ( 字母 ,数字,下划线_ )

\W : 非字符

.(点)——任意字符

\. : 真正的点

\b : 独立的部分 ( 起始,结束,空格 )

\B : 非独立的部分

关于最后两个来看个栗子:

var str = &#39;onetwo&#39;;
var str2 ="one two";
 
var re = /one\b/; // e后面必须是独立的 可以是起始,空格,或结束
 
alert( re.test(str) ); //false
alert( re.test(str2) );//true

例子:写一个用class名获取节点的函数:

我们之前可能见过这样的函数

function getByClass(parent,classname){ 
 if(parent.getElementsByClassName){ 
    return parent.getElementsByClassName(classname);
 }
 else{
  var results = new Array();//用来存储所有取到的class为box的元素
  var elems = parent.getElementsByTagName("*");
  for(var i =0;i<elems.length;i++){ 
   if(elems[i].className==classname){ 
    results.push(elems[i]);
   }
  }
  return results; 
 }
}

其实这是存在问题的,比如它如果一个标签里面有两个class,或者存在相同名字的class,比如e19c23957e0572550417edb1a41b70da,ec144a99e8d5e5c57b576749ea5efb3b它就没办法获取到了,我们可以用正则来解决这个问题。

function getByClass(parent,classname){
    if(parent.getElementsByClassName){ 
       return parent.getElementsByClassName(classname);
    }else{
        var arr = [];
        var aEle = parent.getElementsByTagName(&#39;*&#39;);
        
        //var re = /\bclassname\b/;  //不能这样写,当正则需要用到参数时候,一定要用全称的写法,简写方式会把classname当做一个字符串去匹配。
        var re = new RegExp(&#39;\\b&#39;+classname+&#39;\\b&#39;);  // 匹配的时候,classname前面必须是起始或者空格,后面也是。 默认匹配成功就停止,所以就算有重复的也不会再匹配进去了。
        //需要注意的是,全称的方式声明正则的时候,参数是字符串类型的,所以我们用的时候,需要保证这些特殊的字符在字符串内也能输出才行。\b本身是特殊字符,在字符串中无法输出,所以要加反斜杠转义才行。  
        for(var i=0;i<aEle.length;i++){
            if( re.test(aEle[i].className) ){
                arr.push( aEle[i] );
            }
        }        
        return arr;
    }            
}

\a 表示重复的某个子项 比如:

\1 重复的第一个子项

\2 重复的第二个子项

/ (a) (b) (c) \1/-----匹配 abca
/ (a) (b) (c) \2/------匹配 abcb

例子(面试题中经常问到):找重复项最多的字符个数

split():字符串中的方法,把字符串转成数组。

sort():数组中的排序方法,按照ACALL码进行排序。

join():数组中的方法,把数组转换为字符串

var str = &#39;assssjdssskssalsssdkjsssdss&#39;;
var arr = str.split(&#39;&#39;); //把字符串转换为数组
str = arr.sort().join(&#39;&#39;); //首先进行排序,这样结果会把相同的字符放在一起,然后再转换为字符串
//alert(str);  // aaddjjkklsssssssssssssssss
 var value = &#39;&#39;;
 var index = 0; 
var re = /(\w)\1+/g;  //匹配字符,且重复这个字符,重复次数至少一次。
str.replace(re,function($0,$1){ 
   //alert($0);   代表每次匹配成功的结果 : aa dd jj kk l sssssssssssssssss
     //alert($1);  代表每次匹配成功的第一个子项,也就是\w:  a d j k l S 
  
    if(index<$0.length){  //如果index保存的值小于$0的长度就进行下面的操作
          index = $0.length;  // 这样index一直保存的就在最大的长度
           value = $1;  //value保存的是出现最多的这个字符
    }
}); 
alert(&#39;最多的字符:&#39;+value+&#39;,重复的次数:&#39;+index);  // s   17

量词:代表出现的次数

{n,m}:至少出现n次,最多m次

{n,} :至少n次

* :任意次 相当于{0,}

? :零次或一次 相当于{0,1}

+ :一次或任意次相当于 {1,}

{n}: 正好n次

例子:判断是不是QQ号

//^ : 放在正则的最开始位置,就代表起始的意思,注意  /[^a] /   和   /^[a]/是不一样的,前者是排除的意思,后者是代表首位。
//$ : 正则的最后位置 , 就代表结束的意思

//首先想QQ号的规则 
  1 首位不能是0 
  2 必须是 5-12位的数字
  
 var aInput = document.getElementsByTagName(&#39;input&#39;);
 var re = /^[1-9]\d{4,11}$/;
 //123456abc为了防止出现这样的情况,所以必须限制最后
 //首位是0-9,接着是4-11位的数字类型。
aInput[1].onclick = function(){
 if( re.test(aInput[0].value) ){
  alert(&#39;是QQ号&#39;);
 }else{
  alert(&#39;不是QQ号&#39;);
 }
 
};

例子:去掉前后空格(面试题经常出现)

var str = &#39;  hello  &#39;;
alert( &#39;(&#39;+trim(str)+&#39;)&#39; );//为了看出区别所以加的括号。 (hello)
function trim(str){
   var re = /^\s+|\s+$/g; // |代表或者   \s代表空格  +至少一个    前面有至少一个空格 或者后面有至少一个空格 且全局匹配
  return str.replace(re,&#39;&#39;); //把空格替换成空
}

常用的一些表单校验

匹配中文:[\u4e00-\u9fa5] //中文ACALL码的范围
行首行尾空格:^\s*|\s*$ //首行出现任意个空格或者尾行出现任意个空格(任意表示也可以没有空格)
Email:^\w+@[a-z0-9]+(\.[a-z]+){1,3}$  
      //起始至少为一个字符(\w字母,数字或者下划线),然后匹配@,接着为任意个字母或者数字,\.代表真正的点,.后面为至少一个的字符(a-z),同时这个(比如.com)整体为一个子项作为结束,可以出现1-3次。因为有的邮箱是这样的.cn.net。(xxxx.@qq.com xxxx.@163.com xxxx.@16.cn.net )
网址:[a-zA-z]+://[^\s]*   http://......
  //匹配不分大小写的任意字母,接着是//,后面是非空格的任意字符
邮政编码:[1-9]\d{5}  //起始数字不能为0,然后是5个数字
身份证:[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x

为了方便且不冲突,我们可以用json的格式 建立自己的空间,如下:

/*
 
var re = {
email : /^\w+@[a-z0-9]+(\.[a-z]+){1,3}$/,
number : /\d+/
};
 
re.email
 
*/

所谓温故而知新,可以为师矣,要多多联系。整理的正则的基础知识点大概就这么多,写的有些乱,欢迎指正。

更多教你轻松记住JS正则表达式相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn