zoukankan      html  css  js  c++  java
  • 正则表达式有多强大一看便知!

    正则表达式并不难,只是很多人用得少所以记不住,但并不能否认它的强大之处!

    正则表达式的作用

    1. 校验字符串文本是否符合规则
    2. 提取符合规则的文本内容
    3. 替换文本内容

    正则的字符含义

    字符 描述
    . 匹配除换行符外的任意字符,一个点只能匹配一个
    w 匹配字母数字下划线或者汉字
    W 匹配任意不是字母,数字,下划线,汉字的字符
    s 匹配空白字符,它和[ ]等价(分别是空格制表符换行符回车符)
    S 匹配任意不是空白符的字符
    d 匹配数字(只能表示一位数字,可以替换为[0-9])
    D 匹配任意非数字的字符
     匹配单词的开始或结束
    B 匹配不是单词开头或结束的位置
    ^ 匹配字符串的开始,在列举的上面表示非,如[^d]
    a-Z 匹配a-Z之间的任意字符
    $ 匹配字符串的结束
    * 重复零次或多次
    + 重复一次或更多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次
    () 表示分组,就是括号里面的作为一个整体
    [] 表示字符串的列举

    相关方法

    test()

    • 用于检测字符串是否符合正则规定
    let str = 'javascript'
    let reg = /java/
    // 检测字符串是否包含'java'
    console.log(reg.test(str)); //true
    

    match()

    • match()可以检索一个字符串或者一个正则的匹配,并将匹配到的结果通过数组返回,如果未加全局匹配,则只能通过数组返回匹配到的第一项结果,并会附加信息
    var str="1 plus 2 equal 3"
    console.log(str.match('equal')); //[ 'equal', index: 9, input: '1 plus 2 equal 3', groups: undefined ]
    console.log(str.match(/d+/)); //[ '1', index: 0, input: '1 plus 2 equal 3', groups: undefined ]
    console.log(str.match(/d+/g)); //[ '1', '2', '3' ]
    

    replace()

    • replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串
    • stringObject.replace(regexp/substr,replacement)
      • 参数一为要替换的子字符串或要替换的模式的正则对象
      • 规定了替换文本或生成替换文本的函数
    var str="Visit Microsoft!"
    console.log(str.replace('Microsoft', "W3School")); //Visit W3School!
    console.log(str.replace(/Microsoft/, "W3School")); //Visit W3School!
    

    exec()

    • exec() 方法用于检索字符串中的正则表达式的匹配
    • 通过exec()匹配到的每一项有效结果都会附加信息
    • 在都是非全局匹配的模式下,exec()返回的结果与match()相同;如果是全局匹配,exec()每被调用一次都会返回一项结果数组,直到无法匹配到内容时停下,返回null
    let str="1 plus 2 equal 3"
    let reg = /d/g
    console.log(reg.exec(str)); //[ '1', index: 0, input: '1 plus 2 equal 3', groups: undefined ]
    console.log(reg.exec(str)); //[ '2', index: 7, input: '1 plus 2 equal 3', groups: undefined ]
    console.log(reg.exec(str)); //[ '3', index: 15, input: '1 plus 2 equal 3', groups: undefined ]
    console.log(reg.exec(str)); //null
    

    应用实例

    检测手机号

    • 11位数

    • 第1位为1,第2位在(3,4,5,6,7,8,9)中选1位,3~11位为数字即可

    function isPhoneNumber(tel) {
        var reg =/^1[3-9]d{9}$/;
        return reg.test(tel);
    }
    isPhoneNumber('13997584510')
    

    检测邮箱

    • 以@为分隔符,在@之前以字母、数字开头,之后还可以跟随减号(-)或小数点(.),但不能同时跟随
    • @之后必须紧跟字母或数字
    • 在此之后应紧跟至少一个特殊字符小数点(.)或减号(-),减号(-)可有可无,但是小数点(.)必须存在,并且以小数点后结尾,两种特殊字符也可以共存。不管是小数点(.)还是减号(-),后面都要求跟字母或数字
    function isEmail(str){
    	var reg = /^[A-Za-z0-9]+[-.]*@[A-Za-z0-9]+(-[A-Za-z0-9])*.[A-Za-z0-9]+$/;
    	return reg.test(str);
    }
    isEmail('2270877057@qq.com')
    

    邮箱由于格式种类众多,因此想用一个正则能够检测出所有的邮箱使不现实的,这使得邮箱的检测必定不会完美

    检测密码强度

    • 按照密码强度标准,根据打分机制评定密码强度

    • 长度(25分)

      • 5 分: 小于等于 4 个字符
      • 10 分: 5 到 7 字符
      • 25 分: 大于等于 8 个字符
    • 字母组成(25分)

      • 0 分: 没有字母
      • 10 分: 包含字母但全都是小(大)写字母
      • 25 分: 包含大小写混合字母
    • 数字组成(20分)

      • 0 分: 没有数字
      • 10 分: 1或2个数字
      • 20 分: 大于 2 个数字
    • 其它特殊符号(@#$%^&*)(25分)

      • 0 分: 没有符号
      • 10 分: 1 个符号
      • 25 分: 大于 1 个符号
    • 额外奖励(5分)

      • 2 分: 字母和数字
      • 3 分: 字母、数字和符号
      • 5 分: 大小写字母、数字和符号
    • 最后评分标准:

      分数 等级
      >=90 非常安全
      >=80 安全
      >=70 非常强
      >=60
      >=50 一般
      >=25
      >=0 非常弱
    • 由于检测规则较为复杂,因此借用了方法判断

    // 获取总分数
    function getTotalScore(password) {
        let totalScore = 0
        const regLowLetter = /[a-z]+/g
        const regUpLetter = /[A-Z]+/g
        const regAllLetter = /([a-z]+[A-Z]+)|([A-Z]+[a-z]+)/g
        const regSpecialChar = /[@#$%^&*]+/g
        const specialCharNum = password.match(regSpecialChar) ? password.match(regSpecialChar)[0].length : 0
        const regNumber = /d*/g
        const numberLen = password.length - password.replace(regNumber, '').length
        const extral2 = /^(?=.*[a-zA-Z])(?=.*d).*$/
        const extral3 = /^(?=.*[a-zA-Z])(?=.*d)(?=.*[@#$%^&*]).*$/
        const extral5 = /^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&*]).*$/
    
        // 检测字符长度
        if (password.length >= 8) {
            totalScore += 25
        } else if (5 <= password.length) {
            totalScore += 10
        } else {
            totalScore += 5
        }
        // 检测字母
        if (regAllLetter.test(password)) {
            totalScore += 25
        } else if (regLowLetter.test(password) || regUpLetter.test(password)) {
            totalScore += 10
        } else {
            totalScore += 0
        }
        // 检测数字
        if (numberLen >= 3) {
            totalScore += 20
        } else if (0 < numberLen) {
            totalScore += 10
        } else {
            totalScore += 0
        }
        // 检测其他字符
        if (specialCharNum == 1) {
            totalScore += 10
        } else if (specialCharNum > 1) {
            totalScore += 25
        } else {
            totalScore += 0
        }
        // 额外奖励
        if (extral5.test(password)) {
            totalScore += 5
        } else if (extral3.test(password)) {
            totalScore += 3
        } else if (extral2.test(password)) {
            totalScore += 2
        } else {
            totalScore += 0
        }
        return totalScore
    }
    // 获取级别
    function getRank(password) {
        let totalScore = getTotalScore(password)
        switch (true) {
            case totalScore >= 90:
                console.log('密码非常安全');
                break;
            case totalScore >= 80:
                console.log('密码安全');
                break;
            case totalScore >= 70:
                console.log('密码非常强');
                break;
            case totalScore >= 60:
                console.log('密码强');
                break;
            case totalScore >= 50:
                console.log('密码一般');
                break;
            case totalScore >= 25:
                console.log('密码弱');
                break;
            case totalScore >= 0:
                console.log('密码非常弱');
                break;
        }
    }
    getRank('ahhi1233217890#0')
    

    替换文本

    • 以替换首尾空格为例,模拟trim()方法
    function replaceText(text) {
        var reg = /^s*|s*$/;
        return text.replace(reg, '')
    }
    replaceText('                        Jfsd4324--_ ');
    

    提取文本

    • 将windows后面跟着的版本号一起提取出来
    let text = 'Windows 1.03 and Windows 2.0 fisrt Released in 1985 and 1987 respectively.Windows 95 and Windows 98 are the successor.Then Windows 2000 and Windows Xp appeared.Windows Vista is the Latest version of the family.'
    
    function extractTetx(text) {
        let reg = /Windows ([d.]|[a-zA-Z])+/g
        return text.match(reg)
    }
    console.log(extractTetx(text));
    

    检测身份证

    • 身份证的规则:

      • 15位:ai = xxxxxx yymmdd aa g
      • 18位:ai = xxxxxx yyyymmdd aa g p
      1. x 是6位是地区编码,地区编码首位不能为0

      2. ymd 分别表示年月日,表示出生日期,aa 是随机码,g是性别,p是校验码

    • 校验码计算规则:

      • 前17位号码加权因子为 Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]

      • 验证位 tt = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]

      • 校验码 p = tt[i],其中 ,i是公式除11后取得的余数,如2.31则 i=3,2.37 则 i =4

    • 由于检测规则较为复杂,因此借用了方法判断

    // 判断是否是身份证的核心方法
    function isIDCard(str) {
        let getBirthday
        // 获取身份证最后一位数,用于核对校验码
        let getLastNum = str.slice(-1, )
        if (str.length == 15) {
            getBirthday = str.slice(6, 12)
            // 出生日期核对(15位身份证无校验码)
            if (!(birthRule(getBirthday))) {
                return false
            }
        } else {
            getBirthday = str.slice(6, 14)
            // 校验码与生出日期核对
            if (!(birthRule(getBirthday) && countLastNum(str) == getLastNum)) {
                return false
            }
        }
        // 正则核对
        let reg = /(^[1-9]d{13}(d{3}[Xx]|d{4})$)|(^[1-9]d{11}(d{3}[Xx]|d{4})$)/;
        return reg.test(str);
    }
    // 判断生日是否合法(string:birthday)
    function birthRule(birthday) {
        let year = birthday.slice(0, -4)
        let month = birthday.slice(-4, -2)
        let day = birthday.slice(-2, )
        if (year.length === 2) {
            year = '19' + year
        }
        if (year > new Date().getFullYear() || month > 12) {
            return false
        }
        let days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        // 闰年
        if ((year % 100 !== 0 && year % 4 === 0) || year % 400 === 0) {
            days[1] = 29
        }
        if (day > days[month - 1]) {
            return false
        }
        return true
    }
    // 计算校验码(即使用上述公式)
    function countLastNum(idCard) {
        let tt = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
        let wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
        let arr1 = []
        let totalNum = 0
    
        let arr2 = idCard.slice(0, 17).split('')
        arr2.forEach((item, i) => {
            arr1.push(parseInt(item) * wi[i])
        });
        totalNum = arr1.reduce((total, value) => total + value)
        return tt[mod(totalNum, 11)] - 1
    }
    // 取余函数
    function mod(den, mol) {
        return parseInt((den / mol).toFixed(1).toString().split('.')[1])
    }
    console.log(isIDCard('422301196912307153'));
    

    检测QQ号

    • qq号的规则非常简单:
      1. 5~11位数
      2. 首位不能为0
    function isQQ(qq) {
        var reg = /^[1-9]d{4,10}$/;
        return reg.test(qq);
    }
    console.log(isQQ('13997584510'));
    

    检测微信号

    • 必须以字母开头,可以使用6-20位字母、数字、下划线或减号(-)组合。
    • 不能设置中文
    function isWeiXin(weiXin) {
        var reg = /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/;
        return reg.test(weiXin);
    }
    console.log(isWeiXin('J13997584510'));
    
  • 相关阅读:
    校内题目T2695 桶哥的问题——吃桶
    一位大佬对学习哲理的思考
    P2845 [USACO15DEC]Switching on the Lights 开关灯
    CF911F Tree Destruction
    CF995C Leaving the Bar
    CF997B Roman Digits
    P1667 数列
    P4035 [JSOI2008]球形空间产生器
    P2679 子串
    P2613 【模板】有理数取余
  • 原文地址:https://www.cnblogs.com/jincanyu/p/14773334.html
Copyright © 2011-2022 走看看