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

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

前言

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)$/;  这样才符合我们想要的情况
    */
    
    
  • reg.test(str)

  • str.match(reg)

  • []中出现的规则一般都是本身的含义

    let reg = /^[@+]+$/; // 只能是以@+中的任何一个开头,且它出现一次或者多次的匹配,[]里面的`+`就是本身意义
    
    console.log(reg.test("@@")) // => true
    console.log(reg.test("@@"))
    

    \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
    
  • []中不存在多位数

    let reg = /^[18]$/        
    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 字符内的范围无序

    : 就算在 /^[10-29]$/ 中加入(),\也不行

  • 在写正则表达式的时候一定要注意 顺序是从左往右就近匹配的,善用小整体()
  • 遇到|使用()确定好正则的优先级(()的作用一:细节用法看分析法第一条)
  • 把大正则中的每个小正则 配合 exec方法提取出来(()的作用二:细节用法看分析法第五条)

分析法

1、是否为有效数

  • 有如下数字需要正则匹配():验证是否属于一个合法数字
0
1
12
12.5
12.0
-12
+12
09

提取条件出来:

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

转化为正则表达式

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

2、密码的有效性

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

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

3、真实姓名验证

需求:

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

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

  3. 名字长度2 ~ 10位

    测试用例可以使用:

    • 肯多·洛夫斯基
    • 尼格买提·阿布都
    • 弗拉基米尔·弗拉基米罗维奇·普京
    • 莱昂纳多·迪·皮耶罗·达·芬奇
let reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10})*$/

4、邮箱格式验证

[email protected]

  1. 以数字字母下划线开头(下划线有些邮箱也可以出现多次)
  2. @前面可以是数字、字母、下划线、一、.这些符号
  3. 不能把-和.连续出现,出现一次后面必须跟数字字母下划线
  4. @后面的紧跟数字、字母 ,一到多位
  5. 企业邮箱.com.cn多域名情况
let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;

5、身份证号码验证

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

  1. 目前为止只有18位
  2. 最后一位可能是大写的X (代表是10)
  3. 身份证前6位代表居民所在省、市、县
  4. 中间八位是出生年月日
  5. 最后四位:
    • 最后一位 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 的规则:

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

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

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

利用构造函数方式来获取指定的 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+/

console.log(regex1 === regex2); //两个虽然输出一样,但是不相等
// expected output: false

你可能感兴趣的:(正则表达式入门之踩坑填坑)