1 为什么要用正则表达式?

学习之前,多想想为什么要使用正则表达式,有助于理解。

正则表达式regular expression使用单个字符串来描述某个句法规则,计算机根据规则去匹配字符串中的内容。

  • 正则表达式的性能高于常规字符串操作(省略循环、遍历等操作)

  • 正则表达式仅用于字符串的操作

2 常规字符串操作与正则表达式的比较

要提取出字符串中'ashx521dasbx34sasdz275dasdzxd897'中连续的数字,并将结果保存在数组中['521', '34', '275', '897']

  1. 传统字符串操作:需要遍历整个字符串,判断每个字符是否在'0'-'9'之间再进行相应的操作

    /**
     * 使用一个暂时变量tmp保存连续为数值时的字符串,间断后再统一加入数组内;
     * 可能会出现最后一位是数字的情况,所以使用i<=str.length多走一次循环的else路径,将最后一组数组加入数组
     * 
     */
    function findNum_two(str) {
        var arr = [];
        var tmp = '';
        // 遍历字符串,取出需要的数字
        for(var i=0; i<=str.length; i++) {   
            if(str.charAt(i) <= '9' && str.charAt(i) >= '0') {
                tmp += str[i];
            } else {
                if(tmp) {   // 如果tmp不为空
                    arr.push(tmp);
                    tmp = '';
                }
            }
        }
    
        return arr;
    }
    console.log(findNum_two(str));    //  [ '521', '34', '275', '897' ]
  2. 使用正则表达式:只需使用字符串的match()方法去匹配指定的规则(正则表达式即可)

    function findNum (str) {
        return str.match(/\d+/g);
    }
    
    console.log(findNum(str));   // [ '521', '34', '275', '897' ]

3 正则表达式写法

  1. 字面量写法:var re = /\d+/gi;

  2. 构造函数写法:var re = new RegExp('\\d+', 'gi');注意两个\\,因为JavaScript中\需要转义

图片描述

3.1 正则表达式中的转义字符

转义字符:单独使用字母本身有意义;在前面加上\后改变原有意义

图片描述

3.2 量词

用来描述相邻的前面的单个字符匹配规则出现的次数

  • 量词使用{a, b}表示,其中b可以省略,意义不同

![图片描述

3.3 字符类

  • 使用[]描述一类字符,整体只代表一个字符,表示该字符在某个范围内。

  • /a[0-9]c/匹配三位字符串,第一位是a,第三位是c,第二位是'0'-'9'之间的任何一位都可以匹配成功

  • []多种规则是或 |的关系:[0-9a-zA-Z]

整个字符类[0-9a-zA-Z]只代表一位字符

注意,字符类中的^表示非的意思,不在某个范围内[^\d]表示非数字的字符

3.4 修饰符

  1. g--global:全局匹配,找到所有的匹配项,不是在第一个匹配后停止

  2. i--ignored:忽略大小写

  3. m:多行,将开始字符^和结束字符$视为在多行上工作(每匹配一行的开始和结束以\n\r分割)

  4. u:将模式视为Unicode序列点的序列

3.5 匹配子项

对于复杂的正则表达式,可以使用()将其拆分为多个部分,replace(re, fn)回调函数中可以简化匹配内容的操作

var re = /(\d+)(\w)(\S)/;

fn($0, $1, $2 ...)

  • $0代表正则表达式本身匹配到的内容:(\d+)(\w)(\S)

  • $1代表正则表达式的第一个匹配子项:(\d+)

  • $2代表正则表达式第二个匹配子项:(\w)

  • ...

3.6 重复子项

主要用于匹配字符串中重复的字符

  • var re = /(a)(b)(c)\1/;\1表示重复的第一个子项(b),第4个位置的字符与第1个位置的字符相同

  • var re = /(a)(b)(c)\2/;\2表示重复的第二个子项(b),第4个位置的字符与第2个位置的字符相同

  • var re = /(a)(b)(c)\3/;\3表示重复的第三个子项(c),第4个位置的字符与第3个位置的字符相同

  • ...

3.7 逻辑或|

  • 使用|代表逻辑或,|左右两个操作数只要有一个满足要求即可

3.8 开始、结束标记

  • 不在[]中使用^^表示以最近的匹配字符规则开始整个匹配;

  • $表示以最近的匹配规则结束匹配

作用范围只是^之后的第一个子项;$前的第一个子项

4 正则表达式的方法

主要有4中方法用于操作正则表达式:

  1. match()replace()search()是字符串的操作方法

  2. test()exec()是正则表达式对象的操作方法

4.1 test()

根据RegExp去匹配字符串,如果匹配成功,返回true;匹配失败返回false主要用于逻辑判断

var str = "abxe2312dafxz";
var re = /\d+/;

re.test(str);   // true

4.2 search()

根据RegExp去匹配字符串,返回第一个匹配成功字符串的首字符的索引;匹配失败返回-1用于查找字符的索引,类似字符串的indexOf()方法

  • str.search(re)

4.3 match()

根据RegExp去匹配字符串,如果匹配成功,将匹配的结果保存在数组中返回;匹配失败返回null默认第一次匹配后便停止继续匹配,使用修饰符g进行全局匹配

  • str.match(re)

4.4 replace(re, newstr)方法

根据RegExp去匹配字符串,如果匹配成功,将匹配的字符串更换为新的字符串newstr

replace()方法的参数re正则表达式是变量,必须使用new RegExp()方式创建re

var str = 'a23gb';
var re = /\d+/;

str.replace(re, "xy");   //  'axygb'

replace()方法的第二个参数可以是回调函数,其参数是每次匹配成功获取的字符串。每次匹配成功都会执行一次回调函数

5 实践

5.1 找到一个字符串中出现次数最多的字符及其出现的次数

var str = '1231asdaegj71836178asdhasssasalsdhdzxbczaslazxcnnffajshdhgagsgdssssasdzzxda';

var str = str.split('').sort().join('');   // 按顺序的字符序列

var re = /(\w)\1+/g;

var length = 0;
var val = '';   // 保存出现次数最多的字符

// $0代表每次匹配到的字符,$1代表第一个正则表达式子项(\w)
str.replace(re, function ($0, $1) {  // 可以将匹配的字符当做变量操作
    if($0.length > length) {
        length = $0.length;
        val = $1;    // $1代表每次匹配的字符
    }
});
console.log(length);
console.log(val);

5.2 去掉字符串前后的空格

  • var re = /^\s+|\s+$/g;,使用字符串应用正则即可:str.replace(re, '')

5.3 常用正则匹配规则

  1. QQ号:var re = /^[1-9]\d{4,11}$/; :第一位是1-9中的数字,最后也是数字,总共5-12位

  2. 中文匹配:var re = /[\u4e00-\u9fa5]/;:使用Unicode编码进行匹配

  3. emailvar re = /\w+@[a-z0-9]+(\.[a-z]+){1,3}/;:可能出现.com.cn.net

  4. 身份证:var re = /[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x/i;

  5. 邮编:var re = /[1-9]\d{5}/;

5.3 将常用正则表达式封装在一个对象中便于使用

var re = {
    email: /\w+@[a-z0-9]+(\.[a-z]+){1,3}/,
    chinese: /[\u4e00-\u9fa5]/,
    qq: /^[1-9]\d{4,11}$/,
    id: /[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x/i,
    trim: /^\s+|\s+$/
}

Kyxy
316 声望10 粉丝