正则

114 阅读7分钟

正则

  • 正则表达式, 又名 "规则表达式"
  • 由我们自己来书写 "规则", 专门用来检测 字符串 是否符合 "规则" 使用的
  • 我们使用一些特殊的字符或者符号定义一个 "规则公式", 然后用我们定义好的 "规则公式" 去检测字符串是不是合格
var reg = /\d+/
var str1 = '123'
var str2 = 'abc'
console.log(reg.test(str1)) // true
console.log(reg.test(str2)) // false
  • 上面的变量 reg 就是定制好的规则
  • 检测 str1 这个字符串的时候, 符合规则
  • 检测 str2 这个字符串的时候, 不符合规则

创建一个正则表达式

  • 想制定 "规则", 就必须要按照人家要求的方式来制定
  • 把一些字母和符号写在 // 中间的东西, 叫做正则表达式, 比如 \abcdefg\
  • 创建正则表达式有两个方式 字面量构造函数创建
字面量创建
// 字面量创建一个正则表达式
var reg = /abcdefg/
构造函数创建
var reg = new RegExp('abcdefg')

正则表达式里面的符号

元字符
  • .: 匹配非换行的任意字符
  • \: 转译符号, 把有意义的 符号 转换成没有意义的 字符, 把没有意义的 字符 转换成有意义的 符号
  • \s: 匹配空白字符(空格/制表符/...)
  • \S: 匹配非空白字符
  • \d: 匹配数字
  • \D: 匹配非数字
  • \w: 匹配数字字母下划线
  • \W: 匹配非数字字母下划线

利用元字符制定一些简单的规则

var reg = /\s/
var str = 'a b'
var str2 = 'ab'
console.log(reg.test(str))  // true
console.log(reg.test(str2)) // false
var reg = /\d/
var str = 'abc1'
var str2 = 'abc'
console.log(reg.test(str))  // true
console.log(reg.test(str2)) // false
var reg = /\w/
var str = 'a1'
var str2 = '#$%'
console.log(reg.test(str))  // true
console.log(reg.test(str2)) // false
限定符
  • *: 前一个内容重复至少 0 次, 也就是可以出现 0~正无穷
  • +: 前一个内容重复至少 1 次, 也就是可以出现 1~正无穷
  • ?: 前一个内容重复 0 或者 1 次, 也就是可以出现 0~1
  • {n}: 前一个内容重复 n 次, 也就是必须出现 n
  • {n,}: 前一个内容至少出现 n 次, 也就是出现 n ~ 正无穷
  • {n, m}: 前一个内容至少出现 n 次至多出现 m 次, 也就是出现 n~m

限定符一般是配合元字符使用

var reg = /\d*/ // 验证数字出现 0~正无穷次
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str))  // true
console.log(reg.test(str2))  // true
console.log(reg.test(str3))  // true
var reg = /\d+/ // 验证数字出现 1~正无穷次
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str))  // false
console.log(reg.test(str2))  // true
console.log(reg.test(str3))  // true
var reg = /\d?/ // 验证数字出现 0~1 次都可以
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str))  // true
console.log(reg.test(str2))  // true
console.log(reg.test(str3))  // true
var reg = /\d{3}/ // 验证数字出现 3 次
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
console.log(reg.test(str))  // false
console.log(reg.test(str2))  // false
console.log(reg.test(str3))  // true
var reg = /\d{3,}/ // 验证数字出现 3~正无穷次
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
var str4 = 'abc1234567890'
console.log(reg.test(str))  // false
console.log(reg.test(str2))  // false
console.log(reg.test(str3))  // true
console.log(reg.test(str4))  // true
var reg = /\d{3,5}/ // 验证数字出现 3~5 次
var str = 'abc'
var str2 = 'abc1'
var str3 = 'abc123'
var str4 = 'abc1234567890'
console.log(reg.test(str))  // false
console.log(reg.test(str2))  // false
console.log(reg.test(str3))  // true
console.log(reg.test(str4))  // true
边界符
  • ^: 表示开头
  • $: 表示结尾

边界符是限定字符串的开始和结束的

var reg = /^\d{3,5}$/
var str = 'abc'
var str2 = 'abc123'
var str3 = '1'
var str4 = '1234567'
var str5 = '123'
var str6 = '12345'
console.log(reg.test(str))  // false
console.log(reg.test(str2))  // false
console.log(reg.test(str3))  // false
console.log(reg.test(str4))  // false
console.log(reg.test(str5))  // true
console.log(reg.test(str6))  // true
特殊符号
 /**
     *  正则的特殊元字符
     *
     *      1.  ()
     *              作用1:  单独捕获; 欠着一会讲
     *              作用2:  将括号内的内容, 当成一个整体
     *
     *
     *      2. |    作用: 或者的含义
     *
     *
     *      3. []   作用: 包含
     *                  中括号内 可以有无数个字符, 要求字符串中某一位 是 这个中括号内的内容即可
     *                  注意: 中括号内不管书写多少个字符, 只表示 一位
     *
     *
     *      4. [^]  作用: 不包含
     *
     *
     *      5. -
     *              作用: 到
     *              一般会和  []        或者        [^]     一起使用
     *
     *              案例:   [0-9]   ->  表示 0~9 其中的某一个数字就行
     *              案例:   [a-z]   ->  表示 a~z 其中的某一个小写字母就行
     *              案例:   [^0-9]   ->  表示 0~9 之外的任意一个字符就行
    */


            // 5. - 作用: 到
            // const reg = /^[0-9]$/   // 要求字符串只能是 0~9 之间的某一个数字
            // const reg = /^[a-z]$/   // 要求字符串只能是 a~z 之间的某一个字母
            // const reg = /^[^0-9]$/   // 要求字符串是 0~9 以外的任意一个字符

            // 4. [^]  作用: 不包含
            // const reg = /^abc[^def]$/       // 要求字符串是 abc 开头, 
                                             后边跟一个任意字符 但不能是 def 
                                             其中的某一个

            // console.log(reg.test('abcw'))   // true
            // console.log(reg.test('abcd'))   // false
            // console.log(reg.test('abce'))   // false
            // console.log(reg.test('abcf'))   // false

            // 3. []   作用: 包含
            // const reg = /^abc$/ // 要求字符串必须是 abc 三个小写字母
            // const reg = /^[abc]def$/    // 要求字符串是:    adef;  bdef;   cdef

            // console.log(reg.test('abcdef')) // false
            // console.log(reg.test('adef'))   // true
            // console.log(reg.test('bdef'))   // true
            // console.log(reg.test('cdef'))   // true
            // console.log(reg.test('wdef'))   // false


            // 2. |    作用: 或者的含义
            // const reg = /^a|b$/     // 要求字符串是 a 或者 b
            // console.log(reg.test('a'))  // true
            // console.log(reg.test('b'))  // true
            // console.log(reg.test('c'))  // false





            // 1. ()        将括号内的内容, 当成一个整体
            // const reg = /^abc$/     // 要求字符串必须是 abc 三个小写字母组成
            // console.log(reg.test('abc'))        // true
            // console.log(reg.test('abccc'))      // false
            // console.log(reg.test('abcabcabc'))  // false

            // const reg = /^abc{3}$/     // 要求字符串必须是 abccc 五个小写字母组成
            // console.log(reg.test('abc'))        // false
            // console.log(reg.test('abccc'))      // true
            // console.log(reg.test('abcabcabc'))  // false

            // const reg = /^(abc){3}$/     // 要求字符串必须是 abcabcabc 小写字母组成
            // console.log(reg.test('abc'))        // false
            // console.log(reg.test('abccc'))      // false
            // console.log(reg.test('abcabcabc'))  // true

/**

* 元字符或的特别之处:

     * 
     *      问题: 或 的 分界线在哪里?
     *              是否有小括号
     *                  有: 将左右两边进行拆分, 一直到小括号的位置结束, 不会影响小括号外的正则
     *                  没有:   直接将正则一分为二
     * 
     *      思考下边正则的含义是什么
    */

    /**
     *  含义
     * 
     *      当前正则中, 具有 元字符或       并且没有小括号, 那么直接将正则一分为二
     * 
     *      现在的正则其实是两个, 满足其中一个即可
     *              /^abc/      如果一个字符串是 abc 开头即可
     *              /def$/      如果一个字符串是 def 结尾即可
    */
            const reg_1 = /^abc|def$/
            // console.log(reg_1.test('abc_wertyui9876543@#$%^&*'))    // 当前字符串
                                                                        以 abc 开头
                                                                        
            // console.log(reg_1.test('1234567_def'))    // 当前字符串以 def 结尾
            // console.log(reg_1.test('1234567890qwertyuio@#$%^&*()')) // false

    /**
     *  含义
     * 
     *      当前正则中, 具有元字符或        并且也具有小括号
     *              那么会将或两边的正则分为两个, 但是仅限于 小括号内
     *              所以现在还是一个正则
     * 
     * 
     *      当前正则可以理解为:     /^abc$/     /^def$/
    */
                    const reg_2 = /^(abc|def)$/     
                    // console.log(reg_2.test('abc'))
                    // console.log(reg_2.test('def'))

                    // console.log(reg_2.test('abcd'))
                    // console.log(reg_2.test('cdef'))


    /**
     *  含义
     * 
     *      当前正则中, 具有元字符或        并且也具有小括号
     *              那么会将或两边的正则分为两个, 但是仅限于 小括号内
     *              所以现在还是一个正则
     * 
     *  所以当前正则要求的是        /^abcef$/       /^abdef$/
    */
            // const reg_3  = /^ab(c|d)ef$/

            // console.log(reg_3.test('abcef'))    // true
            // console.log(reg_3.test('abdef'))    // true
            // console.log(reg_3.test('abcdef'))   // false

###### 标识符
* `i`: 表示忽略大小写
    * 这个 i 是写在正则的最后面的, 例如: `/\w/i`
    * 这就是在匹配的时候匹配数字字母下划线, 并且不区分大小写
* `g`: 表示全局匹配,就是从头找到尾
    * 这个 g 是写在正则的最后面的, 例如: `/\w/g`
    * 就是全局匹配数字字母下划线


###### 重复元字符
        * `\数字`: 表示重复第 n 个小括号的内容, 要求和第 n 个小括号的内容一摸一样
```js

        /**
         *  当前正则 中的 \1    是一个重复元字符, 重复的内容是当前正则 第一个小括号匹配的内容
         * 
         *      如果 第一个 小括号中的内容是  div       那么 \1 的值也是 div
         *      如果 第一个 小括号中的内容是  p         那么 \1 的值也是 p
        */
            const reg = /^<(div|p)><\/\1>$/
         console.log(reg.test('<div></div>'))
         console.log(reg.test('<p></p>'))

正则表达式的方法

test 用来检测字符串是否符合我们正则的标准
* 语法: `正则.test(字符串)`
* 返回值: boolean
```js
console.log(/\d+/.test('123'))

* 正则的捕获方法

     * 
     *      捕获其实就是去字符串中寻找符合规则的部分
     * 
     *         exec() 按照正则的内容查找字符,如果查找到返回一个数组,
     *         数组的第0项就是找到的内容,index属性就是找到的下标
     * 
     *      返回值:
     *          没有符合规则的部分: null
     * 
     *          有符合规则的部分: 必然会返回一个数组, 数组[0] 是我们捕获到的内容
     * 
     *              1. 没有 (), 也没有 修饰符g
     * 
     *              2. 有 ()
     *                  会正常返回一个数组, [0] 也是我们捕获到的内容,
                       [1] 开始是我们正则的小括号单独捕获到的内容
     * 
     *              3. 有 修饰符g
     *                 还是按照以前的规则去捕获, 找到之后返回一个 数组, 数组[0]
                       是我们捕获到的内容
     *                 同时 会记录一下 当前捕获到字符串的哪一个位置了,
                       下一次捕获从这个位置开始继续向后捕获
     *                 如果有一次捕获完毕后, 后续没有符合规则的字符了, 
                       那么下一次捕获的时候 返回值为 null
     * 
     *                 如果上一次的捕获结果 为 null, 那么下一次捕获的时候 
                       会重新回到 [0] 的位置开始捕获
    */


    // 3. 有 修饰符g



    // 当前的写法有一个小问题, 每次捕获都是从字符串开头开始捕获, 有一个满足条件后, 
       立马结束, 不在往后继续进行查找
    // const reg = /\d{3}/
    const str = 'qwe123asd456'
    console.log(reg.exec(str))  // ['123', index: 3, input: 'qwe123asd456', groups: undefined]
    console.log(reg.exec(str))  // ['123', index: 3, input: 'qwe123asd456', groups: undefined]
    console.log(reg.exec(str))  // ['123', index: 3, input: 'qwe123asd456', groups: undefined]
   

    const reg = /\d{3}/g
    const str = 'qwe123asd456'
    console.log(reg.exec(str))  // ['123', index: 3, input: 'qwe123asd456', groups: undefined]
    console.log(reg.exec(str))  // ['456', index: 9, input: 'qwe123asd456', groups: undefined]
    console.log(reg.exec(str))  // null
    console.log(reg.exec(str))  // ['123', index: 3, input: 'qwe123asd456', groups: undefined]
    console.log(reg.exec(str))  // ['456', index: 9, input: 'qwe123asd456', groups: undefined]
    console.log(reg.exec(str))  // null


    









    // 2. 有 ()
    const reg = /(\d{3})(\d{3})(\d{3})(\d{3})(\d{3})(\d{3})/
    console.log(reg.exec('411381200510166666'))//['411381200510166666', '411', 
                                            '381', '200', '510', '166', '666',
                           index: 0, input: '411381200510166666', groups: undefined]










    // 1. 没有 (), 也没有 修饰符g
    const reg = /\d{3}/
    console.log(reg.exec('qwe123')) // ['123', index: 3, input: 'qwe123', groups: undefined]
    console.log(reg.exec('QF001'))  // ['001', index: 2, input: 'QF001', groups: undefined]










    // 基本演示
     const reg = /\d{3}/
     console.log(reg.exec('qwertyuiokjnbvcxzasert'))  // null
    console.log(reg.exec('qwe123')) // ['123', index: 3, input: 'qwe123', groups: undefined]
    console.log(reg.exec('QF001'))  // ['001', index: 2, input: 'QF001', groups: undefined]








* 正则的两大特性

     *      1. 贪婪
     *              在捕获的时候, 尽可能的多去拿一些内容
     * 
     *              贪婪限定符, 如果在正则使用, 默认开启 贪婪模式
     *                 ?     {0,1}
                       +      {1,} 
                       *      {0,}
     *                 {n,}
     *                 {n,m}
     *              如果需要开启非贪婪模式, 直接在每一个贪婪限定符后添加一个 ?
     *                  *?
     *                  +?
     *                  ??
     *                  {n,}?
     *                  {n,m}?
     * 
     *      2. 懒惰
     *              在正则中我们每一次捕获都是处于懒惰模式, 那么也就是说, 每一次都会从 [0] 开始捕获
     * 
     *              如果想要开启非懒惰模式, 只需要在 正则的最后添加一个修饰符 g
    */
    const str = '<div class="box" id="qf001"><p>你好, <span>JS</span></p></div>'

    const reg = /<div.*>/
    console.log(reg.exec(str)[0])  // '<div class="box" id="qf001"><p>你好, <span>JS</span></p></div>'


    const reg_1 = /<div.*?>/
    console.log(reg_1.exec(str)[0]) // <div class="box" id="qf001">
    
    
    
    
    
  

* 字符串中能够使用正则的方法

     *
     *      1. replace
     *          字符串.replace('要找的字符串片段', '要加入的新字符串')
     *          字符串.replace(正则, '要加入的新字符串')
     *
     *      2. search
     *          字符串.search('字符串片段')
     *
     *      3. match
     *          字符串.match('字符串片段')
     *          字符串.match('正则')
     * 
     *              如果正则没有修饰符g, 那么作用和 正则的 exec 作用一样
     *              如果正则书写了修饰符g, 那么会字符串中所有符合规则的部分 存放在一个数组中返回
    */



    const str = 'QF001qwe123asd999'

    // console.log(str.match('001'))    // ['001', index: 2, input: 'QF001qwe123asd999', groups: undefined]
    // console.log(str.match(/\d{3}/))     // ['001', index: 2, input: 'QF001qwe123asd999', groups: undefined]
    console.log(str.match(/\d{3}/g))     // ['001', '123', '999']






                // 2. search
                const str = 'QF001'
                         01234
                console.log(str.search('0'))    // 2
                console.log(str.search('9'))    // -1
                console.log(str.search(/\d{1}/))    // 2




    // 1. replace
    let str = 'QWE000ASD000ZXC000'
    str = str.replace('000', '999')
    console.log(str)    // QWE999ASD000ZXC000
    str = str.replace(/\d{3}/, '999')
    console.log(str)    // QWE999ASD000ZXC000
    str = str.replace(/\d{3}/g, '999')
    console.log(str)    // QWE999ASD999ZXC999
    
    

简单的验证

     0-255
    0.0.0.0-255.255.255.255

    用户名验证
    /^\d{8,16}$/

    密码验证  简单
    /^\d{8,16}$|^[a-z]{8,16}$|^[A-Z]{8,16}$/

    邮箱验证
    /^\w+\@\w+\.\w+(\.\w+)?$/

    qq验证
    /^\d{6,11}$/

    手机号验证
    /^1[3-9]\d{9}$/

    身份证
    /^\d{17}(\d|X)$/

    网址 可以判断网站或者ip地址
    /^https?:\/\/((\w+\.\w+(\.\w+)?)|((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(\.(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3}))/
    

    年龄  0-129
    /^\d$|^[1-9]\d$|^1[0-2]\d$/