常用正则表达式及基础知识

正则表达式
基础知识

  • 正则表达式具有特殊含义的标点符号
    ^ $ . * + ? = ! : | \ / ( ) [ ] { }
    想直接使用上面这些标点符号直接量,则必须使用前缀 \ 。
  • 正则表达式的字符类
    字符 匹配
    [...] 方括号内的任意字符
    [^...] 不在方括号内的任意字符
    . 除换行符和其他Unicode行终止符之外的任意字符
    \w 任何ASCⅡ字符组成的单词,等价于[a-zA-Z0-9]
    \W 任何不是ASCⅡ字符组成的单词,等价于[^a-zA-Z0-9]
    \s 任何Unicode空白符
    \S 任何非Unicode空白符的字符,注意\w和\S不同
    \d 任何ASCⅡ数字,等价于[0-9]
    \D 除了ASCⅡ数字之外的任何字符,等价于[^0-9]
    \b 退格直接量
  • 正则表达式的重复字符语法
    字符 含义
    {n,m} 匹配前一项至少n次,至多m次
    {n,} 匹配前一项n次或更多次
    {n} 匹配前一项n次
    匹配前一项0次或1次,也就是说前一项是可选的,等价于{0,1}
    + 匹配前一项1次或多次,等价于{1,}
    * 匹配前一项0次或多次,等价于{0,}
  • 【常用正则表达式及基础知识】正则表达式中的锚字符
    字符 含义
    ^ 匹配字符串的开头,在多行检索中,匹配一行的开头
    $ 匹配字符串的结尾,在多行检索中,匹配一行的结尾
    \b 匹配一个单词的边界,简言之,就是位于字符\w\W之间的位置,或位于字符\w和字符串的开头或者结尾之间的位置(但需要注意,[\b]匹配的是退格符)
    \B 匹配非单词边界的位置
    (?=p) 零宽正向先行断言,要求接下来的字符都与p匹配,但不能包括匹配p的那些字符
    (?!p) 零宽负向先行断言,要求接下来的字符不与p匹配
    \b: 匹配的是单词,而不是单词中的某个部分。并且它只会匹配字符串开头结尾及空格回车等的位置,不会匹配空格符本身。
    比如在句子I like bike中,有很多的i,我只想匹配I这个独立的单词,那么需要使用\bI\b。注意\sI\s匹配的是I(单词前后有空格)。
    先行断言:如果在符号(?=之间加入一个表达式,他就是一个先行断言,用以说明圆括号内的表达式必须正确匹配,但不是真正意义上的匹配。比如,要匹配一种常用的程序设计语言的名字,但只在其后有冒号时才匹配,可以使用/[Jj]ava([Ss]cript)?(?=\:)/,这个正则表达式可以匹配"JavaScript: The Definitive Guide"中的"JavaScript",但是不能匹配"Java in a Nutshell" 中的"Java",因为它后面没有冒号。
  • 用于模式匹配的String方法(4种)
    search()replace()match()split()
  • 密码验证:包含大小写字母,数字,特殊字符
    以上类别都包含:/^(?=.?[a-z])(?=.?[A-Z])(?=.?\d)(?=.?[#@&.]).$/**
    如果是要求包含且只包含:/^(?=.?[a-z])(?=.?[A-Z])(?=.?\d)(?=.?[#@&.])[a-zA-Z\d#@&.]$/*
  • 正则提取字符
    假定我们正在检索的模式是一个或多个小写字母后面跟随了一位或多位数字,则可以使用模式/[a-z]+\d+/。但假定我们
    真正关心的是每个匹配尾部的数字,那么如果将模式的数字部分放到括号中(/[a-z]+(\d+)/),就可以从检索
    到的匹配中抽取数字了。
    var str='translate(12.5,32.1)'; var _str=str.match(/translate\((.*)\)/); console.log(_str);

  • RegExp的方法
    • exec()
      exec()方法对一个指定的字符串执行一个正则表达式。就是在一个字符串中执行匹配检索,如果没有找到任何匹配,它就返回null,但如果它找到了一个匹配,它将返回一个数组。exec()方法与String方法match()相似,只是RegExp方法的参数是一个字符串,而String方法的参数是一个RegExp对象。
    • test()
      参数是一个字符串,用test()对某个字符串进行检测,如果包含正则表达式的一个匹配结果,则返回true。
使用案例
  • 后台传回来时间格式的字符串为2018-01-25 15:19:12.532,我们要转换成时间对象,本地使用Date.parse()去转换带有毫秒的字符串貌似会在ie内核浏览器上转换出错。
    不使用正则表达式:
    var str=`2018-01-25 15:19:12.532`; var objDate=Date.parse(str.replace(/-/g,'/').split('.')[0]);

    使用正则表达式:
    var str=`2018-01-25 15:19:12.532`; // \s表示任何的Unicode空白符,\S表示任何非Unicode空白符,[...]表示方括号内的任意字符,*表示匹配前一项0次或者多次 var objDate=Date.parse(str.replace(/-/g,'/').replace(/\.[\s\S]*/g,''));

  • 特殊字符校验
    var regEn = /[`~!@#$%^&*()_+<>?:"{},.\/; '[\]]/im; var regCn = /[·!#¥(——):;“”‘、,|《。》?、【】[\]]/im; if (regEn.test(value) || regCn.test(value)) { alert('不能使用特殊字符'); return false; }

常用表达式
  • 邮箱
    export const isEmail = (s) => { return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s) }

  • 手机号码
    export const isMobile = (s) => { return /^1[0-9]{10}$/.test(s) }

  • 电话号码
    export const isPhone = (s) => { return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s) }

  • 是否 url 地址
    export const isURL = (s) => { return /^http[s]?:\/\/.*/.test(s) }

  • 是否字符串
    export const isString = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'String' }

  • 是否数字
    export const isNumber = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Number' }

  • 是否 boolean
    export const isBoolean = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Boolean' }

  • 是否函数
    export const isFunction = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Function' }

  • 是否为 null
    export const isNull = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Null' }

  • 是否 undefined
    export const isUndefined = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Undefined' }

  • 是否对象
    export const isObj = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Object' }

  • 是否为数组
    export const isArray = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Array' }

  • 是否时间
    export const isDate = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Date' }

  • 是否正则
    export const isRegExp = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'RegExp' }

  • 是否错误对象
    export const isError = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Error' }

  • 是否Promise对象
    export const isPromise = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Promise' }

  • 是否Symbol函数
    export const isSymbol = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Symbol' }

  • 是否Set对象
    export const isSet = (o) => { return Object.prototype.toString.call(o).slice(8, -1) === 'Set' }

  • 严格的身份证校验
    export const isCardID = (sId) => { if (!/(^\d{15}$)|(^\d{17}(\d|X|x)$)/.test(sId)) { console.log('你输入的身份证长度或格式错误') return false } //身份证城市 var aCity = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古", 21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏", 33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西", 46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏", 65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外" }; if (!aCity[parseInt(sId.substr(0, 2))]) { console.log('你的身份证地区非法') return false }// 出生日期验证 var sBirthday = (sId.substr(6, 4) + "-" + Number(sId.substr(10, 2)) + "-" + Number(sId.substr(12, 2))).replace(/-/g, "/"), d = new Date(sBirthday) if (sBirthday != (d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate())) { console.log('身份证上的出生日期非法') return false }// 身份证号码校验 var sum = 0, weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2], codes = "10X98765432" for (var i = 0; i < sId.length - 1; i++) { sum += sId[i] * weights[i]; } var last = codes[sum % 11]; //计算出来的最后一位身份证号码 if (sId[sId.length - 1] != last) { console.log('你输入的身份证号非法') return false }return true }

  • 检测密码强度
    export const checkPwd = (str) => { var Lv = 0; if (str.length < 6) { return Lv } if (/[0-9]/.test(str)) { Lv++ } if (/[a-z]/.test(str)) { Lv++ } if (/[A-Z]/.test(str)) { Lv++ } if (/[\.|-|_]/.test(str)) { Lv++ } return Lv; }

参考链接
  • 前端常用60余种工具方法

    推荐阅读