• 正则表达式


    定义

    正则表达式(Regular Expression)是一门简单语言的语法规范,是强大、便捷、高效的文本处理工具,它应用在一些方法中,对字符串中的信息实现查找、替换和提取操作。

    javascript中的正则表达式用RegExp对象表示,有两种写法:一种是字面量写法;另一种是构造函数写法。

    • 引用类型
    var expression = /pattern/flags;
    
    var reg = new RegExp();
    var reg = ...;
    
    • 1
    • 2
    • 3
    • 4

    ​ g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止。

    i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写。

    m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。

    ​ ECMAScript3规范规定,一个正则表达式直接量会在执行到它时转换为一个RegExp对象,同一段代码所表示正则表达式直接量的每次运算都返回同一个对象。ECMAScript5规范则做了相反的规定,同一段代码所表示的正则表达式直接量的每次运算都返回新对象。IE6-8一直是按照ECMAScript5规范的方式实现的,所以并没有兼容性问题。

    RegExp构造函数

    ​ 和普通的内置对象一样,RegExp正则表达式对象也支持new+RegExp()构造函数的形式

    RegExp构造函数接收两个参数:要匹配的字符串模式(pattern)和可选的标志字符串(flags),标志字符串和字面量的三个标志含义相同:‘g’、‘i’、‘m’

    RegExp构造函数的两个参数都是字符串。且使用字面量形式定义的任何表达式都可使用构造函数

    方法

    exec():返回目标字符串中符合表达式的部分

    test(): 判断目标字符串是否满足表达式,返回boolean

    let reg2 = /ab/;
    console.log(reg2.exec("abc"));//ab
    console.log(reg2.exec("keabc"));//ab
    console.log(reg2.test("ceg"));//false
    
    • 1
    • 2
    • 3
    • 4

    特点

    ​ javascript 中的正则表达式最大的特点是不支持空白,必须写在一行中。

    //匹配ab
    console.log(/ab/.test('ab')); //true
    console.log(/ ab/.test('ab')); //false
    console.log(/a b/.test('ab')); //false
    console.log(/ab /.test('ab')); //false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    元字符

    ​ 大部分字符在正则表达式中,就是字面的含义,比如/a/匹配a,/b/匹配b。

    /dog/.test("old dog") // true
    
    • 1

    ​ 但还有一些字符,它们除了字面意思外,还有着特殊的含义,这些字符就是元字符

    在javascript中,共有14个元字符(meta-character):

    () [] {} \ ^ $ | ? * + .
    
    • 1
    元字符         名称              匹配对象
    .             点号              单个任意字符(除回车\r、换行\n、行分隔符\u2028和段分隔符\u2029外)
    []            字符组             列出的单个任意字符
    [^]           排除型字符组        未列出的单个任意字符
    ?             问号               匹配0次或1*             星号               匹配0次或多次
    +             加号               匹配1次或多次
    {min,max}     区间量词           匹配至少min次,最多max次
    ^             脱字符             行的起始位置
    $             美元符             行的结束位置
    |             竖线               分隔两边的任意一个表达式
    ()            括号               限制多选结构的范围,标注量词作用的元素,为反向引用捕获文本
    \1,\2...      反向引用            匹配之前的第一、第二...组括号内的表达式匹配的文本
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    例:

    /a[efg]/.test("cbaebj")//true a后面必须接着efg中任意一个字符
    /a[^efg]/.test("weaf"));//false,a后面必须是除了efg任意一个或多个字符
    /a?/.test("bde"); //true 匹配到a一次,或0次
    /a{1,3}/.test("bbabdlj") //true,匹配到a最少一次最多3次
    /^abc$/.test("abbbabbdlj")	//false,必须以a开头连接b,且结束字符是c
    /ab(a|b)/.test("abc")		//ab后面的字符可以是a或b
    /ab(a|b)(c|a)\2/.test("abbcc") //true ab后面的字符可以是a或b,接着的字符可以是c或a,接着的字符必须与第二个括号匹配结果相同,例如:第二个括号给的字符是a,那么\2也必须是a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    转义字符

    转义字符(escape)表示为反斜线()+字符的形式,共有以下3种情况:

    • 因为元字符有特殊的含义,所以无法直接匹配。如果要匹配它们本身,则需要在它们前面加上反斜杠

    • \ 加任意其他字符,默认情况就是匹配此字符,也就是说,反斜线被忽略了

    • \ 加非元字符,表示一些不能打印的特殊字符

      \t制表符\u0009
      \n		换行符\u000A
      \r 		回车符\u000D
      \0		空字符
      
      • 1
      • 2
      • 3
      • 4
    • 即:\ 可以进行普通符号与特殊符号之间的转换

    字符组和范围

    ​ 字符组(Character Class),用方括号表示的一组字符,匹配到它若干字符之一,正则表达式通过连字符(-)提供了范围表示法,可以简化字符组:

    /[0123456789]/		等价于		/[0-9]/
      
    /[abcdefghijklmnopqrstuvwxyz]/	等价于		/[a-z]/
    
    • 1
    • 2
    • 3

    ​ 在字符组中可以同时并列多个’-'范围:

    /[0-9a-zA-Z]/;//匹配数字、大写字母和小写字母
    /[0-9a-fA-F]/;//匹配数字,大、小写形式的a-f,用来验证十六进制字符
    
    console.log(/[0-9a-fA-F]/.test('d'));//true
    console.log(/[0-9a-fA-F]/.test('x'));//false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    排除

    ​ 字符组的另一个类型是排除型字符组,在左方括号后紧跟一个脱字符’^'表示,表示在当前位置匹配一个没有列出的字符。

    //匹配第一个是数字字符,第二个不是数字字符的字符串
    console.log(/[0-9][^0-9]/.test('1e'));//true
    console.log(/[0-9][^0-9]/.test('q2'));//false
    
    • 1
    • 2
    • 3

    简记

    ​ 用[0-9]、[a-z]等字符组,可以很方便地表示数字字符和小写字母字符。对于这类常用字符组,正则表达式提供了更简单的记法,这就是字符组简记(shorthands)。

    常见的字符组简记有\d、\w、\s。其中d表示(digit)数字,w表示(word)单词,s表示(space)空白。

    正则表达式也提供了对应排除型字符组的简记法:\D、\W、\S。字母完全相同,只是改为大写,这些简记法匹配的字符互补。

    \d     数字,等同于[0-9]
    \D     非数字,等同于[^0-9]
    \s     空白字符,等同于[\n\r\t]
    \S     非空白字符,等同于[^\f\n\r\t\u000B\u0020\u00A0\u2028\u2029]
    \w     字母、数字、下划线,等同于[0-9A-Za-z_](汉字不属于\w)
    \W     非字母、数字、下划线,等同于[^0-9A-Za-z_]
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    量词

    {n}       匹配n次
    {n,m}     匹配至少n次,最多m次
    {n,}      匹配至少n次
    ?         相当于{0,1}
    *         相当于{0,}
    +         相当于{1,}
    
    /(ab){3}/.test('lka') false   必须匹配到ab两次,且两次连接在一起
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    贪婪模式

    ​ 默认情况下,量词都是贪婪模式(greedy quantifier),即匹配到下一个字符不满足匹配规则为止,也可以理解为拿到最长的结果:

    //exec()方法以数组的形式返回匹配结果
    /a+/.exec('aaa'); // ['aaa']
    /a+/.exec('aaaba'); // ['aaa']
    
    • 1
    • 2
    • 3

    懒惰模式

    ​ 懒惰模式(lazy quantifier)和贪婪模式相对应,在量词后加问号’?'表示,表示尽可能少的匹配,一旦条件满足就不往下匹配,也可以理解为拿到最短的结果:

    {n}?       匹配n次
    {n,m}?     匹配至少n次,最多m次
    {n,}?      匹配至少n次
    ??         相当于{0,1}
    *?         相当于{0,}
    +?         相当于{1,}
    
    /a+?/.exec('aaa'); // ['a']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    括号

    ​ 用于限定量词或选择项的作用范围,用于捕获文本并可以进行引用:

    console.log(/(ab){2}/.test('abab'));//true,必须匹配到ab两次,且两次连接在一起
    console.log(/(ab){2}/.test('abb'));//false
    console.log(/ab{2}/.test('abab'));//false
    console.log(/ab{2}/.test('abb'));//true,必须匹配到bb
    
    • 1
    • 2
    • 3
    • 4

    匹配模式

    ​ 匹配模式(match mode)指匹配时的使用的规则。设置特定的模式,可能会改变对正则表达式的识别。前面已经介绍过创建正则表达式对象时,可以设置’m’、‘i’、'g’这三个标志,分别对应多行模式、不区分大小模式和全局模式三种:

    ​ i:默认地,正则表达式是区分大小写的,通过设置标志’i’,可以忽略大小写(ignore case)

    console.log(/ab/.test('aB'));//false
    console.log(/ab/i.test('aB'));//true
    
     let reg2 = /a/;
    console.log(reg2.exec("Aaaaaaababaabbcccc"));//{"a", index=1}
    let reg1 = /a/i;
    console.log(reg1.exec("Aaaaaaababaabbcccc"));//{"A", index=0}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ​ m:默认地,正则表达式中的^和$匹配的是整个字符串的起始位置和结束位置,而通过设置标志’m’,开启多行模式,它们也能匹配字符串内部某一行文本的起始位置和结束位置(multiline)

    console.log(/world$/.test('hello world\n')); //false
    console.log(/world$/m.test('hello world\n')); //true
    
    console.log(/^b/.test('a\nb')); //false
    console.log(/^b/m.test('a\nb')); //true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ​ g:默认地,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),设置’g’标志后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换

    console.log('1a,2a,3a'.replace(/a/,'b'));//'1b,2a,3a'
    console.log('1a,2a,3a'.replace(/a/g,'b'));//'1b,2b,3b'
    
    • 1
    • 2

    优先级

    ​ 正则表达式千变万化,都是由之前介绍过的字符组、括号、量词等基本结构组合而成的

    //从上到下,优先级逐渐降低
    \                            转义符
    () []              括号、字符组
    * + ? {n} {n,} {n,m}         量词
    ^ $                          起始结束位置
    |                            选择
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    例题:

    let emailReg = /^[a-z][a-z0-9_]{5,15}@(163|qq|live|sina|126|yeah|outlook)\.(com|cn|net|org)$/
    // 以小写英文字符开头,后面的字符可以是任意小写父母或数字范围是5-15位,后面接@,再接163|qq|live|sina|126|yeah|outlook中的任意一个,接普通字符.,接com|cn|net|org中任意一个作为结束字符串
    /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
    console.log(emailReg.test("twae345@163.com"))//true
    
    let tmp = /^1[3-9]\d{9}$/
    console.log(tmp.test("13469933141"))//true
    //以1开头,第二位可以是3-9,接9位任意数字
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    例如:使用正则表达式,找出所有的 / ,并删除

    "中国/湖北省/武汉市/黄冈/.../../..".replace(/\//g, '')
    
    • 1

    身份证号

    18位
    (1)1~6位为地区代码,其中1、2位数为各省级政府的代码,3、4位数为地、市级政府的代码,5、6位数为县、区级政府代码。
    首位以1-9开头,后5位为0-9 /1\d{5}/
    (2)7~10位为出生年份(4位) 1800-2399 /(19|20|21)\d{2}/
    (3)11~12位为出生月份 /(0[1-9])|(1[0-2])/.test(‘01’)必须是字符不能是数字01,会自动编译成1
    (4)13~14位为出生日期 /[0-2][1-9]|10|20|30|31/
    (5)第15~17位为顺序号,为县、区级政府所辖派出所的分配码,每个派出所分配码位10个连续号码,例如“150—159”,其中单数为男性分配码,双数为女性分配码,如遇同年同月同日有两人以上时顺延第二、第三、第四、第五个分配码。 /\d{3}/
    (4)18位为效验位(识别码),通过复杂公式算出,普遍采用计算机自动生成。 /[0-9X]/

    15位
    (1)1~6位为地区代码
    (2)78位为出生年份(2位),910位为出生月份,11~12位为出生日期
    (3)第13~15位为顺序号,并能够判断性别,奇数为男,偶数为女。

    let idcardReg18 =''
    /^[1-9]\d{5}(19|20|21)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/6| 年份          |  月份    	     |  日期				     |3|校验码
     
    let idcardReg15 =''
    /^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}$/6| 年份后两位 + 月份    	|  		 日期	             |3
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1. 1-9 ↩︎

  • 相关阅读:
    Mybatis详解
    场景应用:线程池的队列大小你通常怎么设置?
    871. 最低加油次数 : 简单优先队列(堆)贪心题
    【微客云】提供三网92折话费充值API接口稳定到账独立后台售后服务(帮你对接小程序app)
    Jenkins安装配置及插件安装使用
    Java9-17新特性解读,了解少于3个你可能脱节了
    张宇30讲学习笔记
    动态内存管理
    HotSpot 虚拟机对象探秘-对象的创建、内存布局、访问定位
    “理解梯度下降:直觉、数学公式和推导”
  • 原文地址:https://blog.csdn.net/Sandersonia/article/details/132664725