51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

JS正则表达式使用详解

文章已同步至掘金:https://juejin.cn/post/6844903954254413837
欢迎访问😃,有任何问题都可留言评论哦~

正则表达式很不容易看懂,就算你看完了所有的字符代表的含义,你可能还是一脸懵逼
所以我认为需要把字符所代表的含义和例子结合起来,一起看,这样就会很容易看懂的

语法结构 {#%E8%AF%AD%E6%B3%95%E7%BB%93%E6%9E%84}

/正则表达式主体/修饰符(可选)

修饰符:

  • i (搜索不区分大小写)
  • g (全局匹配)
  • m (执行多行匹配)
  • u (匹配宽字节)

使用字面量创建 {#%E4%BD%BF%E7%94%A8%E5%AD%97%E9%9D%A2%E9%87%8F%E5%88%9B%E5%BB%BA}

let str = 'fanjunyang'

let dete = 'j'

`console.log(eval(``/${dete}/``).test(str));	// true
`

元字符 {#%E5%85%83%E5%AD%97%E7%AC%A6}

常用元字符:

| 代码 | 说明 | |------|-------------------| | . | 匹配除换行符以外的任意字符 | | * | 匹配前面的字符或子表达式零次或多次 | | \w | 匹配字母或数字或下划线或汉字 | | \s | 匹配任意的空白符 | | \d | 匹配数字 | | \b | 匹配单词的开始或结束 | | ^ | 匹配字符串的开始 | | $ | 匹配字符串的结束 |


\b代表着 单词的开头或结尾,也就是单词的分界处
通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置

他代表精确查找 ,如果你想查找he,有的单词里包含了he,比如:helloheadhere
如果你只想精确的查找到he,你就可以这样写:\bhe\b


.表示匹配除换行符以外的任意字符
*表示匹配前面的子表达式零次或多次

如果你的he单词后面的不远处跟着xi,你可以这样用:\bhe\b.*\bxi\b
这里*定义了前面的.可以是零次或多次


^表示匹配字符串的开始
$表示 匹配字符串的结束

这和\b有点类似

示例:
^abc:匹配所有以 abc 开始的字符串 (例如:abcabcxxx
abc$:匹配所有以abc 结尾的字符串 (例如:abcxxxabc
^abc$:匹配开始和结尾都为abc的字符串 (例如:abc

如果什么都不加的话,则匹配所有,如:
abc:没有任何字符,匹配任何包含abc的字符串 (例如:aaaabcccabc12312abc65


\w\d\s,如果理解了上面几个的话,这几个就比较好理解了

示例:
\bh\w*\b他表示匹配以字母h开头的单词-->先是某个单词开始处\b,然后是字母h,然后是任意数量的字母或数字\w*,最后是单词结束处\b

1\d\d\d\d\d\d\d\d\d\d他表示的就是以数字1开头的11位的手机号(好像只有1开头的手机号),当然也可以写成1\d{10},后面会说

\s没什么好说的,就是匹配空白符,比如你输入一串英文,然后你换行了,或者使用空格键或者Tab键,你就可以使用\s


反义 {#%E5%8F%8D%E4%B9%89}

有时需要查找不属于某个能简单定义的字符类的字符。
比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义:

| 代码\语法 | 说明 | |--------|-----------------------| | \W | 匹配任意不是字母,数字,下划线,汉字的字符 | | \S | 匹配任意不是空白符的字符 | | \D | 匹配任意非数字的字符 | | \B | 匹配不是单词开头或结束的位置 |


示例:
[^x]:匹配除了x以外的任意字符
[^aeiou]:匹配除了aeiou这几个字母以外的任意字符
\S+:匹配不包含空白符的字符串。
a[^>]+>:匹配用尖括号括起来的以a开头的字符串。


字符转义 {#%E5%AD%97%E7%AC%A6%E8%BD%AC%E4%B9%89}

如果你想查找元字符本身的话,比如你查找.或者*,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。

这时你就得使用\来取消这些字符的特殊意义
因此,你应该使用\.\*。当然,要查找\本身,你也得用\\

例如:
www\.baidu\.com匹配 www.baidu.com
E:\\file匹配 E:\file


重复 {#%E9%87%8D%E5%A4%8D}

常用限定符:

| 代码/语法 | 说明 | |---------|----------| | * | 重复零次或更多次 | | + | 重复一次或更多次 | | ? | 重复零次或一次 | | {n} | 重复n次 | | {n,} | 重复n次或更多次 | | {n,m} | 重复n到m次 |


上面已经说过了*,所以这里就不难理解了

示例:
\bh\w*\b他表示匹配以字母h开头的单词-->先是某个单词开始处\b,然后是字母h,然后是任意数量的字母或数字\w*,最后是单词结束处\b

\bh\w+\b他表示匹配以字母h开头的单词-->先是某个单词开始处\b,然后是字母h,然后是一次或多次的字母或数字\w+,最后是单词结束处\b

第一种情况可以是h,而第二种情况就不能是h,后面必须跟上别的

至于?,就只能是h,或者h后面再加一个字符,不能加多


^\d{9}$表示匹配9位数的数字,比如我的QQ号,996597002,这里指定了位数9,所以必须是9位

可以这样写^\d{5,12}$,表示匹配 5~12 位的数字,而^\d{5,}$表示数字的位数,至少是5位或更多次


字符类 {#%E5%AD%97%E7%AC%A6%E7%B1%BB}

这里就不列表了,直接上例子:

|表示或
例如:a|b:表示一个字符串里有 a 或者 b (例如:abababc

符号[]定义了一个字符集合,可以匹配[]之中的任意一个成员文本。

例如:

  • [abc]可以匹配 abc
  • [.?!] 可以匹配标点符号(.或?或!)
  • [0-9]代表的含意与\d完全一致
  • [^abc]任何字符,除了 abc(否定)
  • [a-zA-Z] azAZ,两头的字母包括在内(范围)
  • [a-d[m-p]] admp[a-dm-p](并集)
  • [a-z&&[def]] def(交集)
  • [a-z&&[^bc]] az,除了 bc[ad-z](减去)
  • [a-z&&[^m-p]] az,而非 mp[a-lq-z](减去)

来个复杂的表达式:\(?0\d{2}[) -]?\d{8}
这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或 02912345678等
分析:首先是一个转义字符\(,它能出现0次或1次?,然后是一个0,后面跟着2个数字\d{2},然后是)-空格中的一个,它出现1次或不出现?,最后是8个数字\d{8}


分组和分支 {#%E5%88%86%E7%BB%84%E5%92%8C%E5%88%86%E6%94%AF}

分组主要是括号的使用

分组和分支结构
在分支结构中,括号是用来表示一个整体的,比如要匹配下面的字符串

I love JavaScript
I love Express

可以用:/^I love (JavaScript|Express)$/,而不是:/^I love JavaScript|Express$/

表示一个整体还比如 /(abc)+/ 一个或者多个 abc 字符串
上面这些使用括号包起来的地方就叫做分组

'I love JavaScript'.match(/^I love (JavaScript|Express)$/)
// ["I love JavaScript", "JavaScript", index: 0, input: "I love JavaScript"]

输出的数组第二个元素,JavaScript 就是分组匹配到的内容


引用分组 {#%E5%BC%95%E7%94%A8%E5%88%86%E7%BB%84}

提取数据
比如我们要用正则来匹配一个日期格式,yyyy-mm-dd
可以写出简单的正则/\d{4}-\d{2}-\d{2}/,这个正则还可以改成分组形式的/(\d{4})-(\d{2})-(\d{2})/

这样我们可以分别提取出一个日期的年月日,用 String 的 match 方法或者用正则的 exec 方法都可以

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2019-09-27";
console.log( string.match(regex) ); 
// => ["2019-09-27", "2019", "09", "27", index: 0, input: "2019-09-27"]

也可以用正则对象构造函数的全局属性 $1 - $9 来获取

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2019-09-27";

regex.test(string); // 正则操作即可,例如
//regex.exec(string);
//string.match(regex);

`console.log(RegExp.$1); // "209"
console.log(RegExp.$2); // "09"
console.log(RegExp.$3); // "27"
`

替换
如果想要把 yyyy-mm-dd 替换成格式 mm/dd/yyyy 应该怎么做。
String 的 replace 方法在第二个参数里面可以用 $1 - $9 来指代相应的分组

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2019-09-27";
var result = string.replace(regex, "$2/$3/$1");
console.log(result); // "09/27/2019"
等价
var result = string.replace(regex, function() {
    return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1;
});
console.log(result); // "09/27/2019"
等价
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2019-09-27";
var result = string.replace(regex, function(match, year, month, day) {
    return month + "/" + day + "/" + year;
});
console.log(result); // "09/27/2019"

反向引用 {#%E5%8F%8D%E5%90%91%E5%BC%95%E7%94%A8}

匹配日期的正则在使用的时候有好几种写法,例如:

2019-09-27
2019/09/27
2019.09.27

要匹配这三种应该怎么写正则,第一反应肯定是把上面那个正则改一下/(\d{4})[-/.](\d{2})[-/.](\d{2})/,把 - 改成 [-/.] 这三种都可以
看上去没问题,我们多想想就会发现,这个正则把 2019-09.27 这种字符串也匹配到了,这个肯定是不符合预期的。

这个时候我们就需要用到反向引用了,反向引用可以在匹配阶段捕获到分组的内容 /(\d{4})([-/.])(\d{2})\2(\d{2})/

如果出现括号嵌套,那么嵌套的括号以左括号为准
如果在正则里面引用了前面不存在的分组,这个时候正则会匹配字符本身,比如\1就匹配\1


贪婪与惰性 {#%E8%B4%AA%E5%A9%AA%E4%B8%8E%E6%83%B0%E6%80%A7}

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符

例如:a.*b,它将会匹配最长的以a开始,以b结束的字符串
如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配


有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符
前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的字符,但是在能使整个匹配成功的前提下使用最少的重复。

例如:a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。


懒惰限定符:

| 代码/语法 | 说明 | |----------|------------------| | *? | 重复任意次,但尽可能少重复 | | +? | 重复1次或更多次,但尽可能少重复 | | ?? | 重复0次或1次,但尽可能少重复 | | {n,m}? | 重复n到m次,但尽可能少重复 | | {n,}? | 重复n次以上,但尽可能少重复 |

其他的就不说了,大同小异


整理的不好,多多包涵

最后给大家推荐一个很强大的正则网站:https://regex101.com/

常用数字正则校验 {#%E5%B8%B8%E7%94%A8%E6%95%B0%E5%AD%97%E6%AD%A3%E5%88%99%E6%A0%A1%E9%AA%8C}

验证数字:^[0-9]*$
验证n位的数字:^\d{n}$
验证至少n位数字:^\d{n,}$
验证m-n位的数字:^\d{m,n}$
验证零和非零开头的数字:^(0|[1-9][0-9]*)$
验证有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
验证有1-3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
验证非零的正整数:^\+?[1-9][0-9]*$
验证非零的负整数:^\-[1-9][0-9]*$
验证非负整数(正整数 + 0)  ^\d+$
验证非正整数(负整数 + 0)  ^((-\d+)|(0+))$
验证长度为3的字符:^.{3}$
验证由26个英文字母组成的字符串:^[A-Za-z]+$
验证由26个大写英文字母组成的字符串:^[A-Z]+$
验证由26个小写英文字母组成的字符串:^[a-z]+$
验证由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
验证由数字、26个英文字母或者下划线组成的字符串:^\w+$
验证用户密码:^[a-zA-Z]\w{5,17}$ 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线。
验证是否含有 ^%&',;=?$\" 等字符:[^%&',;=?$\x22]+
验证汉字:^[\u4e00-\u9fa5]*$
验证Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
验证InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
验证电话号码:^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$:--正确格式为:XXXX-XXXXXXX,XXXX-XXXXXXXX,XXX-XXXXXXX,XXX-XXXXXXXX,XXXXXXX,XXXXXXXX。
验证身份证号(15位或18位数字):^\d{15}|\d{}18$
验证一年的12个月:^(0?[1-9]|1[0-2])$ 正确格式为:"01"-"09"和"1""12"
验证一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$    正确格式为:01、09和1、31。
整数:^-?\d+$
非负浮点数(正浮点数 + 0):^\d+(\.\d+)?$
正浮点数   ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
非正浮点数(负浮点数 + 0) ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
负浮点数  ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数  ^(-?\d+)(\.\d+)?$

@@ {#%40%40}

赞(2)
未经允许不得转载:工具盒子 » JS正则表达式使用详解