正则表达式入门之踩坑填坑

正则表达式常见坑与分析法

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions

这个开发者文档就是好,讲得比w3school还清楚
稍稍看看文档,对照着就开始用吧。

为啥要用正则呢?不用多说了吧,一行正则匹配,顶上十来行字符串[拼接、分割、截取]的操作

字符串中的斜杆 \ 转义 的特殊意义,在写正则规则的时候请注意 \ 代表的意思

字符串中两个 \ 代表一个

/^ $/ 中间的内容是只能包含的意思,而不是很多教程中提到的 以xxx开头 ,以xxx结尾,多了一层 并且 的意思,所以规则是 只能

/^a$/ 匹配以a开头,以a结尾的字符 所以 只能是a

/^ab$/ 匹配以a开头,以b结尾的字符 所以只能是 ab

x|y 迷惑的 | 匹配运算,优先级很混乱记得搭配上 () 来使用, () 在正则中表示一个分组匹配意为先 结合 解决优先级问题

let reg = /^18|29$/;
console.log(reg.test("1829")) //=> true 
console.log(reg.test("189"))  //=>true
console.log(reg.test("129"))  //=>true
console.log(reg.test("89"))     //=>false
let reg = /^(18|29)$/;  这样才符合我们想要的情况
let reg = /^[@+]+$/; // 只能是以@+中的任何一个开头,且它出现一次或者多次的匹配,[]里面的`+`就是本身意义
console.log(reg.test("@@")) // => true
console.log(reg.test("@@"))

\color{#e15c5f}{注意例外}\d组合词的本身含义就是 0 ~ 9

let reg = /^[\d]$/ // => 这个 `\d` 还是原始的 `\d`的意思 0 ~ 9 之间的数字
console.log(reg.test("d"))  //false
console.log(reg.test("\\")) //false
console.log(reg.test("9"))  //true
console.log(reg.test("8")) //true
console.log(reg.test("9")) //true
console.log(reg.test("18")) //false

此处翻译为: 只能是 1 或者 8

let reg = /^[10-29]$/

此处翻译为:只能是 1 或者 0到2 或者9

let reg = /^[18-29]$/

而这里会提示 是错误的正则式,Range out of order in character class 字符内的范围无序

\color{#ff0000}{注意}: 就算在 /^[10-29]$/ 中加入(),\也不行

  • 遇到|使用()确定好正则的优先级(()的作用一:细节用法看分析法第一条
  • 把大正则中的每个小正则 配合 exec方法提取出来(()的作用二:细节用法看分析法第五条
  • 1、是否为有效数

  • 有如下数字需要正则匹配():验证是否属于一个合法数字
  • 提取条件出来:

    1. 可能出现 + - 号,也可能没有,且有且只有一个 2. 0 - 9 都可以,但是多位数首位不能是 0 3. 小数部分可能有,可能没有,有的话有且只有一个点,且点后必须有数字

    转化为正则表达式

    let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
    [+-]?  +或者-出现 0 或者 1 次
    (+|-)? 与上面相等
    (\d|([1-9]\d+))
    \d为出现一位,
    或者多位时,首位不能为零,则再用一个 () 表示一个小分组,且每次遇到 | 的时候使用 ()包起来
    ([1-9]\d+)  这里表示小分组是 或的另外一边的一个整体, 1 - 9 出现一次 或者多次
    + 为匹配前面的表达式出现一次或者多次
    

    2、密码的有效性

    需求:密码是 6 - 16位,可以是数字、字母、下划线

    let reg = /^(\w){6,16}$/

    3、真实姓名验证

  • 验证汉字:/^[\u4E00-\u9FA5]$/

  • 有可能是翻译过来的汉字名:肯多·洛夫斯基,也可能是新疆人名字尼格买提·阿布都(·汉字)

  • 名字长度2 ~ 10位

    测试用例可以使用:

  • 肯多·洛夫斯基
  • 尼格买提·阿布都
  • 弗拉基米尔·弗拉基米罗维奇·普京
  • 莱昂纳多·迪·皮耶罗·达·芬奇
  • let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
    

    5、身份证号码验证

    中国第二代居民身份证规则为:

  • 目前为止只有18位
  • 最后一位可能是大写的X (代表是10)
  • 身份证前6位代表居民所在省、市、县
  • 中间八位是出生年月日
  • 最后四位:
  • 最后一位 X 或者 数字
  • 倒数第二位 偶数为女 ,奇数为男
  • 其余两位是经过算法 结合前6、中8,后2位算出来的(非随机)
  • /*如果只考虑位数与字符,不考虑字符意义*/
    let reg = /^(\d+){17}(\d|X)$/
    let reg = /^(\d+X{0,1}){18}$/   /*这样写不行,必须拆开前17位  + 后一位才行*/
    
    /*附带意义的匹配*/
    let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|X)$/
    reg.exec("430181199003073470")
    

    使用exec来捕获()匹配出来的每一个小分组,结果为:

    ["430181199003073470", "430181", "1990", "03", "07", "34", "7", "0", index: 0, input: "430181199003073470", groups: undefined]
    

    6、获取cookie值

    cookie 的规则:

  • 字符串开头有可能有空格,可能没有(第一条就没有)

  • 接着后面是 key= 的固定样式

  • 字符串结束有可能有分号,可能没有(最后一条没有分号)

  • 利用构造函数方式来获取指定的 cookie key 名的值

    function (key) {
        let reg = RegExp("(^| )"+key+"=([^;]*)(;|$)");
    * exec 有几个括号就至少有几个分组
    * 匹配一个开头,空格可有可无 (可能匹配的是第一条,所以空格可有可无)
    * 接着后面的 字符是 key=
    * 匹配任何没有包含在方括号中的字符 (只要不是分号就可以) 
    * 星号 = {0,} 出现零次或者多次,意味着   cookie有时候会是 null值
    * 匹配结束 分号可有可无(可能匹配的是最后一条,所以分号可有可无)(只能包含 ^ $ 中间的东西)
    
    [" name=zhangsan", " ", "zhangsan", "", index: 22, input: "age=21; handsome=true; name=zhangsan", groups: undefined]
    
    如果 传入参数 name,匹配之后:
    * 可以看到 name 前面有空格,
    * 第一项为 匹配出来的总结果
    * 第二项的 " " 为 小分组 (^| ) 所捕获
    * 第三项的 "zhangsan" 为 小分组([^;]*)所捕获   这正是我们想要的
    * 第四项的 "" 为 小分组(;|$) 所捕获
    // 返回的数组中  input 是原生字符串 是 document.cookie
    

    正则表达式的两种创建方式

    1、字面量方式

    let reg = /@+name+/
    

    / /中间包含的任意字符都会被识别成为 正则表达式的元字符

    如果这个时候要将 传过来的变量 name来进行独立的个体匹配,那是不行的,这个时候就应该用 构造函数方式来创建 字符串拼接的表达式

    注意:使用正则表达式字面量为正则表达式提供了脚本加载后的编译。当正则表达式保持不变时,使用此方法可获得更好的性能

    2、构造函数方式

    new RegExp(pattern,flags)
    

    pattern:正则表达式

    flags:匹配模式

    let reg = new RegExp("@"+name+"+")
    

    且在使用模式的时候需要传入第二个参数flags

    字面量的方式可以紧随最后一个/其后

    注意:使用构造函数为正则表达式提供了运行时的编译。使用构造函数的方式,当你知道正则表达式的模式将会改变,或者你不知道模式,并且从其他来源获取它,如用户输入。

    var regex1 = /\w+/;
    var regex2 = new RegExp('\\w+'); //在字符串中 单条斜杆加上斜杆后字符代表转义字符
    console.log(regex1);
    // expected output: /\w+/
    console.log(regex2);
    // expected output: /\w+/