前言
各位同仁在表单验证规则,或者在验证数据的时候,是不是经常都是xxx.xxxx,然后对数据处理来处理去,最后进行后续操作……,不仅费时费力,而且消耗精神,于是乎:
ps(我):要不要用用正则,但是想不起来怎么写啊,百度搜一下吧,chatGpt搜一下,贴上去
我:欧哟?刚刚好啊,效果还怪好的嘞,哈哈哈,天助我也!
这还是好的情况,刚刚好符合,要是不好……
ps(我):服了,这正则不得行,chatGpt搜的错的,自己写吧又不会,找吧又没有……
我:乖乖写if else吧
又是啃哧啃哧,耗时耗力……可能大家伙都是差不多的哈,谁也别说谁(大佬除外)。本着多一事不如少一事的原则,直接学习一波!
js正则表达式
正则(正则表达式)是一种用于描述文本模式的工具,它通过使用特定的符号和语法规则来定义一个字符串的模式。正则表达式通常由各种字符和特殊元字符组成,用于进行字符串匹配、查找、替换和验证等操作。
使用正则表达式,可以执行以下操作:
- 模式匹配:正则表达式可以用于查找和匹配具有特定模式的字符串。通过定义一个模式,可以搜索和识别符合该模式的字符串。
- 字符串查找与替换:正则表达式可以用于在文本中进行字符串查找和替换。通过指定要查找或替换的模式,可以对目标字符串进行修改和处理。
- 数据验证:正则表达式可以用于验证用户输入或其他数据的格式和有效性。例如,可以使用正则表达式验证电子邮件地址、电话号码、日期等的格式是否符合预期。
- 文本提取:在文本处理中,可以使用正则表达式从大量文本数据中提取出所需的信息。例如,可以使用正则表达式从日志文件中提取特定的时间戳或关键字。
- 数据清洗与转换:使用正则表达式,可以进行文本数据的清洗和转换。可以根据模式匹配和替换规则,删除非法字符、规范化日期格式、提取关键信息等。
正则表达式提供了一种强大和灵活的文本处理工具,它被广泛应用于编程语言、文本编辑器、数据处理工具等各种软件中。虽然正则表达式的语法可能会显得复杂,但掌握它可以极大地提高对文本模式处理的能力。
应用
正则表达式在计算机科学和文本处理中具有广泛的应用。以下是一些常见的正则表达式应用:
- 模式匹配:正则表达式可用于检测字符串是否与特定模式匹配。例如,可以使用正则表达式来验证电子邮件地址、检查电话号码的格式、识别日期等。
- 字符串搜索与替换:正则表达式可以用于在文本中搜索特定的模式,并进行替换或提取。这对于在大量文本中进行批量操作非常有用,如查找和替换文本文件中的特定单词或短语。
- 表单验证:在前端开发中,可以使用正则表达式验证用户输入的表单数据。例如,验证用户名是否只包含字母和数字、检查密码是否符合指定的复杂度要求等。
- URL路由:许多Web框架使用正则表达式来解析URL路由和处理动态路由。它们通过正则表达式匹配URL字符串并将其映射到相应的处理程序或控制器。
- 日志分析:使用正则表达式可以解析和提取日志文件中的有用信息。例如,可以使用正则表达式从服务器日志中提取IP地址、日期时间戳、错误消息等。
- 数据清洗与转换:正则表达式可用于清洗和转换数据,如从多种格式的文本数据中提取特定字段、规范化日期格式、去除特殊字符等。
- 编程工具与编辑器:许多编程工具和文本编辑器支持正则表达式搜索和替换功能。这使得开发人员能够更灵活地进行代码重构和批量修改操作。
创建正则
js 中内置了正则表达式对象 RegExp
,我们要创建一个正则表达式,可以:
- 第一种创建方式,接收
pattern
和modifiers
两个参数
var regex = new RegExp(pattern, modifiers);
var regex = new RegExp('xyz', 'i');
var regex = /xyz/i;
RegExp
构造函数接收两个参数,pattern
描述了表达式的模式,为字符串,modifiers
是正则表达式的修饰符,用于执行区分大小写和全局匹配。
- 第二种创建方式,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。
var regex = new RegExp(/xyz/i);
var regex = /xyz/i;
在构造函数创建时 pattern
是正则字符串,字面量创建时,pattern
是一个类似 /正则规则/
表达式,是放在双斜杠里的。
modifiers
有三个值,分别为
值 | 描述 |
---|
i | 不区分大小写。在匹配时忽略大小写 |
g | 全局匹配。查找所有可能的匹配,而不仅仅是第一个匹配。 |
s | 单行匹配。启用单行模式,使点号(.)可以匹配包括换行符在内的任意字符。 |
u | 启用完整的 Unicode 匹配支持,会正确处理四个字节的 UTF-16 编码。 |
m | 多行匹配。启用多行模式,^ 和 $ 可以匹配行的开始和结束。 |
例如,使用 i
和 g
修饰符创建一个忽略大小写和全局匹配的正则表达式:
javascript
var pattern = new RegExp("pattern", "ig")
或者使用字面量表示法也可以传递修饰符:
var pattern = /pattern/ig
正则对象的方法
正则表达式对象通常提供一组方法,用于在字符串上执行不同的操作。以下是一些常见的正则表达式对象的方法:
test(string)
: 检测指定字符串是否与正则表达式匹配。返回一个布尔值,表示是否找到匹配项。一般开发当中,我们使用这种方法较多。
const regex = /apple/;
console.log(regex.test("I love apples"));
console.log(regex.test("I prefer oranges"));
exec(string)
: 在给定字符串中搜索匹配项,并返回一个数组或 null。数组包含有关匹配项的详细信息,如匹配的子字符串、捕获组等。
const regex = /\d+/;
console.log(regex.exec("I have 100 apples"));
console.log(regex.exec("There are no numbers here"));
match(regexp)
: 在字符串中查找与正则表达式匹配的内容,并返回一个数组或 null。类似于 exec()
方法,但是 match()
是在字符串上调用,而不是在正则表达式上调用。
const string = "I have 100 apples";
const regex = /\d+/;
console.log(string.match(regex));
search(string)
: 在字符串中搜索与正则表达式匹配的内容,并返回匹配项的索引。如果没有找到匹配项,则返回 -1。
const string = "I prefer oranges";
const regex = /oranges/;
console.log(string.search(regex));
replace(regexp, replacement)
: 替换字符串中与正则表达式匹配的部分。可以将匹配项替换为指定的字符串或使用函数进行替换。
const string = "I like cats and dogs"
const regex = /cats/
const replacement = "birds"
const newString = string.replace(regex, replacement)
console.log(newString)
split(regexp)
: 将字符串分割为由正则表达式匹配的子字符串组成的数组。正则表达式定义了分隔符。
const string = "apple,banana,orange"
const regex = /,/
const parts = string.split(regex)
console.log(parts)
正则规则
分为基本字符匹配;元字符匹配,如\w
;锚点匹配指定匹配发生的位置, 如^
表示匹配行的开头;量词和限定符, 如*
; 分组和捕获()
;零宽断言:正向肯定断言 (?=...)
:匹配满足断言条件的位置,但不会消耗字符;
接下来一一进行介绍。
基本字符匹配
匹配字面量字符/ /
如果想在javaScript
当中直接匹配java
,可以直接在我们的字面量当中写入想要匹配的值,即java直接进行匹配。
正则: /java/
可以匹配的 | 不能匹配的 |
---|
javascript | Javascript |
java | jaava |
字符组[ ]
如果不仅仅想要匹配java
还想要匹配Java
,那光光/java/
是不够的。这时候还需要用到我们的字符组。
正则:/[Jj]ava/
可以匹配的 | 不能匹配的 |
---|
javascript | jaava |
Javascript | jvav |
在[]
匹配规则当中,目标字符可以匹配中括号里面的任意一个字符即可,转为javaScript语言
就是 ||
的意思。观察两个目标字符串,java与Java的区别也仅仅是首字母不同,那么只需要兼容开头的大小字母即可。
拓展
若是想匹配java
Java
JAva
,正则需要如何编写?通过观察各个字符当中的差别,即前两个字母的可能性都可能为大小写,便得出前两个位置的匹配使用字符组即可。
正则:/[J][Aa]va/
字符组区间 -
如果说只想匹配前缀为123,后面是二十六个字母当中任何一个的字符怎么办?
这简单,刚刚学完字符组,我直接一手/123[a,b,c,d....]/
把二十六个字母全部列一遍,话虽如此,但大可不必!
此处若是可选匹配字母过多的话,可直接使用字符组区间连接
正则: /123[a-zA-Z]/
可以匹配的 | 不能匹配的 |
---|
123a | 123 |
123B | 12345 |
同时还可以匹配多个数字,比如我只想匹配[3-9]的数字,那么也可以使用连接符
正则123[3-9][a-zA-Z]
可以匹配的 | 不能匹配的 |
---|
1233a | 123a9 |
1236B | 123B |
字符组取反:[^]
有的时候你可能也不想匹配某些字符,比如只晕小写字母,那么这个时候你可以对你所要匹配的字符组进行取反,那就匹配不到了。
正则:/[^a-z]/
可以匹配的 | 不能匹配的 |
---|
1233ABCDE | abcde |
12345678 | adasd |
123adasd | adasd |
注意: 此处需要全部为小写字母test匹配结果才是false
,若字符包含其他的字符,test的匹配结果仍然为true。
const pattern = /[^a-z]/
const string = '123adasd'
pattern.test(string)
元字符匹配
日常开发当中,元字符单独使用的情况并不多,更多的是跟随后续的量词一块使用,最终形成限定字符格式的正则。
单点 .
.
是一个特殊的元字符,可以用于匹配除了换行符 \n
(或其他行终止符,如 \r
或 \n
)之外的任意单个字符。
正则:/./
数字 \d
\d
可以匹配任意一个数字字符,包括 0 到 9 的数字。
字符 \w
用于匹配字母字符、数字和下划线。
具体来说,\w
匹配以下字符:
- 小写字母(a-z)
- 大写字母(A-Z)
- 数字(0-9)
- 下划线(_)
空白符 \s
用于匹配空白字符
- 空格符(Space)
- 制表符(\t)
- 换行符(\n)
- 回车符(\r)
- 垂直制表符(\v)
- 换页符(\f)
注意:如果说想要匹配正则当中的匹配规则符号,例如只想匹配单点字符.
,则需要使用反斜杠进行转义,即/\./
任何匹配正则当中具有意义的字符都需要进行转义。
量词
量词用于指定模式重复出现的次数。允许你匹配一定数量的字符或子模式,是正则当中见怪不怪的玩意。与上述字符相互搭配,能获得意想不到的结果。
量词 {}
用于匹配前面的字符或子表达式指定的精确的重复次数。
比如需要匹配重复多个字符,如需要匹配出现两次a
的字符串。
正则:/a{2}/
但是我只知道会出现a
字符,可能是两到三个呢?这个时候就可以使用区间来表示,囊括出现的次数。
正则:/a{2,3}/
可以匹配的 | 不能匹配的 |
---|
aaa | bbbb |
aabb | abb |
aaab | abab |
如果只知道出现一次,但是不清楚具体有几次,便直接可以不写右区间,表示至少出现n次,比如下面的正则就表示至少出现3次a
正则:/a{3,}/
可以匹配的 | 不能匹配的 |
---|
aaa | bbbb |
baaaa | aabb |
量词 +
用于匹配前面的字符或子表达式至少一次或多次出现。
实际上,+
的表现形式,还可以用{1,}
来表示
正则: /a+/
等价于 /a{1,}/
量词 *
用于匹配前面的字符或子表达式出现0次或多次出现。实际上,*
的表现形式,也可以用{0,}
来表示
正则: /a*/
等价于 /a{0,}/
量词 ?
用于匹配前面的字符或子表达式零次或一次。实际上,*
的表现形式,也可以用{0,1}
来表示
正则: /a?b/
等价于 /a{0,1}b/
正则表达式的贪婪匹配和非贪婪匹配是用来描述匹配模式时的两种不同行为。
贪婪匹配是指正则表达式尽可能地匹配更长的文本片段。它会尽量多地消耗输入字符串,并尝试匹配满足整个正则表达式模式的最长可能结果,是默认的行为,
反之,非贪婪匹配(也称为懒惰匹配或最小匹配) 则是指正则表达式尽可能地匹配更短的文本片段。它会尽量少地消耗输入字符串,并尝试匹配满足整个正则表达式模式的最短可能结果。
通常非贪婪匹配通过在正则字符串后面加?号来表示。
示例
正则表达式 /a+/
,它表示匹配一个或多个连续出现的字符 "a"。
对于字符串 "aaa",贪婪匹配将尽量匹配更长的连续的 "a" 字符串,在这种情况下会匹配整个字符串 "aaa"。
使用非贪婪匹配需要在量词后面添加 ?
。正则表达式 /a+?/
表示非贪婪匹配,将匹配一个或多个连续出现的字符 "a",但只尽量匹配最短的结果。非贪婪匹配将尽量匹配最短的连续的 "a" 字符串。在这个例子中,非贪婪匹配会匹配第一个 "a" 字符,因为它是最短的满足正则表达式模式的子串。
锚点匹配
锚点是正则表达式中的特殊字符,用于匹配字符串的位置而不是具体的字符,可用于指定匹配发生的位置,常用的锚点有^
、$
、\b
。
^ 起始位置
表示匹配行的开头。下面正则表示匹配以a为开头的字符
正则:^a
$ 结束位置
表示匹配行的结尾。下面正则表示匹配以a为结尾的字符
正则:a$
\b 边界
表示匹配单词边界。下面正则表示匹配独立的单词
正则:/\bapple\b/
可以匹配的 | 不能匹配的 |
---|
I love apple | pineapple |
apple | pinapple |
\b还有很多其他的应用,比如
\b\w+\b
:匹配一个或多个连续的单词字符,可以用来分割句子为单词数组。
\b\d{4}\b
:匹配仅包含4位数字的字符串
在转义\b的时候需要使用\\b
分组和捕获:
分组 ()
括号 ( ):用于将一组模式作为单个单元进行匹配,并将其视为一个分组。
比如,我要匹配以js
、ts
、java
后缀的文件
正则:/.*\.(js|ts|java)/
可以匹配的 | 不能匹配的 |
---|
index.js | 1.png |
1.ts | 2.jpg |
calss.java | 3.mp3 |
再比如 正则:/(ab){1,}
/,可以匹配一个或出现多个连续的ab,利用分组实现的
捕获组
通过圆括号捕获分组内的内容,可以在后续操作中进行引用。
可能这比较难理解,我们举例说明,比如,我们有1-8
、2-2
这种类型的数据,我们可以使用正则的分组将两边的数据包裹,并使用exec进行捕获。分组符号的数据就是把这些想要捕获的数据标记出来。
如果我们想要 ()
的分组能力,但是又不想捕获数据,可以使用 (?:)
表达式。可以提高正则表达式的性能和简洁性。
零宽断言
- 正向肯定预查
(?=...)
:表示在当前位置后面,如果满足括号内的表达式,则继续匹配成功。
- 正向否定预查
(?!...)
:表示在当前位置后面,如果不满足括号内的表达式,则继续匹配成功。
- 反向肯定预查
(?<=...)
:表示在当前位置前面,如果满足括号内的表达式,则继续匹配成功。
- 反向否定预查
(?<!...)
:表示在当前位置前面,如果不满足括号内的表达式,则继续匹配成功。
/(?=\d)\w+/
匹配由数字紧随其后的单词字符。
| 可以匹配的 | 不能匹配的 |
| --- | --- |
| 1 | w |
| 1w | ww |
为什么这里能匹配1呢?1首先同样属于字符,其次还是数字,在断言的时候,不消耗字符,符合数字随其后的规则(本身)
/(?<!\d)\w+/
匹配没有数字紧随在前面的单词字符。(js不支持)
js并不支持反向预查,只支持正向预查。这是因为正向预查在匹配时,可以当前位置后面的内容进行断言判断,如果不符合预期,则无法继续匹配成功。这种类型的预查可以通过回溯来实现。
然而,反向否定预查需要从当前位置回溯到前面的位置进行条件判断,这就使得正则引擎需要逆序地扫描前面的内容,增加了匹配的复杂度。因此,实现反向否定预查的算法相对更为复杂,并且可能导致性能下降。
反向否定预查在某些特定情况下可以被其他模式替代,比如使用捕获组结合后续的处理代码来达到类似的效果。
正则表达式大全
- 邮箱验证
/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(.\w{2,3})+$/
^\w+
匹配以字符开头,([.-]?\w+)*
部分出现两次,品牌包含一个或多个由-
或点.
连接的部分,(.\w{2,3})+
匹配域名
- URL 验证:包括 HTTP 和 HTTPS 协议。
/^(https?://)?[\w-]+(.[\w-]+)+[/#?]?.*$/
- 身-份-证号码验证:验证中国大陆身-份-证号码的有效性。
低配:
/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
高配:
身-份-证号匹配
/^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[1-2]\d|3[0-1])\d{3}[0-9Xx]$/
^[1-9]\d{5}
:匹配 6 位行政区划代码、
(19|20)\d{2}
:年份,匹配以 19 或 20 开头的四位数字、
(0[1-9]|1[0-2])
:月份,取值范围为 01 到 12、
(0[1-9]|[1-2]\d|3[0-1])
:日期,取值范围为 01 到 31、
\d{3}
:顺序码,任意三位数字、
[0-9Xx]
:校验码,可以是数字或字母 X 或 x、
- 数字验证:用于验证一个字符串是否只由数字组成。
`/^\d+$/`
- 字母验证:用于验证一个字符串是否只由字母组成。
`/^[a-zA-Z]+$/`
- 小数验证:匹配的数字可包含小数点,此处转义了小数点,
/^\d+(\.\d+)?$/
- 整数验证(包括负数):用于验证一个字符串是否为整数,可以包含正负号。
`/^[-+]?\d+$/`
- IP 地址验证: 用于验证 IPv4 地址的有效性。
/^((25[0-5]|2[0-4]\d|[01]?\d\d?).){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
- 手机号码验证:
低配版本,仅表示11位数字
```
^\d{11}$ 低配版本,11位数字
```
高配版本
```
/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/
如果不想这么复杂,可以写为
/^1[3-9]d{9}$/
还能匹配*特殊符号的,但是会失去匹配11位数功能
/^1[3-9]\d{1}(?:\*{1,})*\d+$/
```
如果确定符号个数,可改为/^1[3-9]\d{1}((?:\*{4})|\d{4})\d{4}$/
,就能匹配固定11位数的号码
- 可以匹配
152702365242
- 可以匹配
152****65242
10.密码复杂度要求
?=
为正向断言,判断条件是否符合.*\d
,即任意字符但是需要出现一个数字,其余类似
这个正则表达式用于强制密码应至少包含一个数字(?=.*\d)
、一个小写字母(?=.*[a-z])
和一个大写字母(?=.*[A-Z])
,并且长度至少为8个字符.{8,}
。
11.以8结尾,且位数在6位以内的数字
/^\d{0,5}8$/
- 时间匹配,匹配时分,年月日的匹配建议还是按照Date的API,正则在匹配闰年的二月份时候无法匹配
/^(?:[01]\d|2[0-3]):(?:[0-5]\d)$/
- 可以匹配
09:10
12:12
23:01
23:59
/^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/
(?!0000)
表示后面不能跟着四个0,即年份不能为0000。
[0-9]{4}
表示匹配四个数字,即年份的格式为四位数字。
-
表示匹配“-”字符。
(?:…)
表示非捕获型分组,用于提高正则表达式的效率。
(?:0[1-9]|1[0-2])
表示匹配01-12月份,其中0[1-9]
表示01-09月份,1[0-2]
表示10-12月份。
(?:0[1-9]|1[0-9]|2[0-8])
表示匹配01-28日,其中0[1-9]
表示01-09日,1[0-9]
表示10-19日,2[0-8]表示20-28日。
(?:0[13-9]|1[0-2])-(?:29|30)
表示匹配01、03、05、07、08、10、12月份的29或30日。
(?:0[13578]|1[02])-31
表示匹配01、03、05、07、08、10、12月份的31日。
(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29
表示匹配闰年的2月29日,其中[0-9]{2}表示匹配两位数字的年份,(?:0[48]|[2468][048]|[13579][26])表示匹配闰年的年份,即能被4整除但不能被100整除,或者能被400整除。
$
表示匹配字符串的结束位置。
- 用户名:4-10位的用户名,包含下划线、连接符
/^[a-zA-Z0-9_-]{4,10}$/
总结
以上就是目前能想到的常用的正则,大家如果也有或者说常用的正则,也可以在评论区反馈,谢谢各位!
作者:原野风殇
来源:juejin.cn/post/7299376141451411490