[TOC] 参考链接 面试官!让我们聊聊正则
正则表达式 - 元字符!!! 一直以来正则都靠搜索,复制粘贴。今天开始学习,以后就可以自己写啦~~~
正则表达式是什么
正则表达式(Regular Expression)是一个描述字符模式的对象,使用正则表达式可以进行强大的模式匹配和文本检索与替换功能。 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。
正则表达式是处理字符串的利器,并提高工作效率,一个好的正则能够帮我们省去几十甚至上百行代码。
入门
学习正则表达式最好方法是从例子开始,理解例子之后再对例子进行修改,实验。
常用正则表达式
- 姓名
- 2-9位中文昵称:
^[\u4e00-\u9fa5]{2,9}$
- 2-9位中文昵称:
- 验证密码
- 只能是数字、字母、下划线,长度不限制:
^\w+$ - 允许 小写字母 a-z、大写字母 A-Z、数字 0-9、下划线 _、 连接符 -,且长度在 6-18 位数:
/^[a-zA-Z0-9_-]{6,18}$/ - 必须包含数字+小写字母+大写字母的密码,且长度在8-10位之间:
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
- 只能是数字、字母、下划线,长度不限制:
- 验证 Email
- 允许有一个字符符合 [A-Za-z0-9_] 之后可以为 [A-Za-z0-9_-+.] + @ + 允许有一个字符符合 [A-Za-z0-9_] 之后可以为 [A-Za-z0-9_-.] + . + 允许有一个字符符合 [A-Za-z0-9_] 之后可以有 [A-Za-z0-9_-.] 的邮箱:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
- 验证身份证
- 18 位身份证号,尾数是数字或者字母 X:
^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$ - 15 或者 18 位身份证号,尾数可以是数字及 X 或者 x:
(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
- 18 位身份证号,尾数是数字或者字母 X:
- 验证手机号
- 以 1 开头,第二位数是 3/4/5/7/8 的 11 位手机号码:
^1[3,4,5,7,8,9]\d{9}$ - 移动号码:
^134[0-8]\d{7}$|^(?:13[5-9]|147|15[0-27-9]|178|1703|1705|1706|18[2-478])\d{7,8}$ - 电信号码:
^(?:133|153|1700|1701|1702|177|173|18[019])\d{7,8}$ - 联通号码:
^(?:13[0-2]|145|15[56]|176|1704|1707|1708|1709|171|18[56])\d{7,8}|$
- 以 1 开头,第二位数是 3/4/5/7/8 的 11 位手机号码:
- 验证电话号码正则
// 匹配格式:
// 11位手机号码
// 3-4位区号,7-8位直播号码,1-4位分机号
export const phoneReg = /^(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/;
// 校验文件名中包含 []{}&, 特别注意,[必须是单独的,]必须是\]
/[[\]{}&]/g.test(i.name);
"^\d+$" //非负整数(正整数 + 0)
"^[0-9]*[1-9][0-9]*$" //正整数
"^((-\d+)|(0+))$" //非正整数(负整数 + 0)
"^-[0-9]*[1-9][0-9]*$" //负整数
"^-?\d+$" //整数
"^\d+(\.\d+)?$" //非负浮点数(正浮点数 + 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+)?)|(0+(\.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+)?$" //浮点数
"^[A-Za-z]+$" //由26个英文字母组成的字符串
"^[A-Z]+$" //由26个英文字母的大写组成的字符串
"^[a-z]+$" //由26个英文字母的小写组成的字符串
"^[A-Za-z0-9]+$" //由数字和26个英文字母组成的字符串
"^\w+$" //由数字、26个英文字母或者下划线组成的字符串
"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$" //email地址
"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$" //url
实现手机号前带86或是+86的情况:^((\+86)|(86))?(13)\d{9}$
电话号码与手机号码同时验证:(^(\d{3,4}-)?\d{7,8})$|(13[0-9]{9})
提取信息中的网络链接:(h|H)(r|R)(e|E)(f|F) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?
提取信息中的邮件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
提取信息中的图片链接:(s|S)(r|R)(c|C) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)?
提取信息中的IP地址:(\d+)\.(\d+)\.(\d+)\.(\d+)
提取信息中的中国手机号码:(86)*0*13\d{9}
提取信息中的中国固定电话号码:(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}
提取信息中的中国电话号码(包括移动和固定电话):(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}
提取信息中的中国邮政编码:[1-9]{1}(\d+){5}
提取信息中的中国身份证号码:\d{18}|\d{15}
提取信息中的整数:\d+
提取信息中的浮点数(即小数):(-?\d*)\.?\d+
提取信息中的任何数字 :(-?\d*)(\.\d+)?
提取信息中的中文字符串:[\u4e00-\u9fa5]*
提取信息中的双字节字符串 (汉字):[^\x00-\xff]*
JavaScript 创建正则表达式
两种方式:
- 用
/正则表达式/两个斜杠来包裹要写的正则表达式 - 构造函数创建(不推荐)
var reg = new RegExp('\\d+', 'img')第一个参数是元字符并且\d这种特殊字符在这里面是普通字符,所以需要用\转义为特殊字符,第二个参数是修饰符
这两种的用途有区别,一般需要动态创建正则元字符采用构造函数创建,因为里面元字符是字符串拼接,常规固定写死正则采用字面量创建,例子如下:
var reg = /^[a-z0-9_-]{6,12}$/
这就是一条规则。
如何匹配一个字符串。这里用test方法
var str = 'abc-cba_abc';
var reg = /^[a-z0-9_-]{6,12}$/;
console.log(reg.test(str)); // true
reg 通过 test() 方法去测试 str 是否符合 reg的规则,如果符合则返回 true,如果不符合则返回 false。 这里返回的是 true,因为我们的 str 是符合 reg 规则的。
基础
要想玩转正则首先要明白三大元素:修饰符 元字符 量词
例:var reg = /^\d$/g 这是一个简单点正则,下面我们来对三大元素一探究竟
1. 修饰符
g- global 全局匹配(只要有匹配成功的结果一直匹配直到没有为止)i- ignoreCase 忽略大小写m- multiline 多行匹配
2. 元字符
元字符分为特殊元字符和普通元字符 普通元字符就是列入数组,字母等元素 常用特殊元字符如下:
-
\转义字符(把一个普通字符转变为有特殊意义的字符,或者把一个有意义的字符转变为普通字符) -
.除了\n(换行符)以外的任意字符 -
\d匹配一个0~9之间的数字 -
\D匹配一个非0~9之间的数字(大写与小写字母组合正好是相反含义 -
\w匹配一个0~9或字母或_之间的一个字符 -
\s匹配一个任意空白字符 -
\b匹配一个边界符 -
x|y匹配x或者y中的一个 -
[a-z]匹配a-z中的任意一个字符 -
[^a-z]匹配非a-z中的任意一个字符 -
[x- yz]匹配x或y或z中的一个字符 -
[^xyz和上方相反 -
()整的小分组,匹配一个小分组(可以理解为大正则中的一个小正则) -
^以某一个元字符开始。例:var reg = /^2/;表示开头必须是2,如果开始元字符放在[]里面 例:[^]表示非中括号种情况 相反含义 -
$以某一个元字符结束。例:var reg = /2$/;表示结尾必须是2,如果是var reg = /^2$/;表示只能为2,因为2只代表一个元字符。 -
?:只匹配不捕获 -
?=正向肯定预查 -
?!正向否定预查
使用解析
1. () 小分组 匹配子项
匹配子项,就是小括号(),也叫分组操作。
| 表达式 | 释义 | 用法 |
|---|---|---|
| (子表达式) | 标记一个子表达式的开始和结束位置。 | (\w)\1 能匹配 deep 中的 ee |
var reg = /^18|19$/
// 这个例子很多同学能够了解是18或者19开头 但是结尾呢?真的只匹配19么? 其实并不是
// 正确的匹配除了18 19 还有181、189、819 这时候小分组就起到了作用如下
var reg = /^(18|19)$/
// 这里将18或19用()包裹起来,起到小分组的作用
// 这样这个正则只匹配18开头结尾或者19而不是181和189
var re = /(\d+)(-)/g;
分析这个正则:
/(\d+)/表示任意 1 个及以上的数字/(-)/表示匹配字符 -g表示匹配一次以上
所以这段正则的意思就是匹配一次及以上的 数字- 形式的字符串。
var str = "2018-11-28";
var re = /(\d+)(-)/g;
str = str.replace(re, function($0, $1, $2){
// 第一个参数:$0(母亲)
// 第二个参数:$1(第一个孩子)
// 第三个参数:$2 (第二个孩子)
console.log("$0:" + $0);
console.log("$1:" + $1);
console.log("$2:" + $2);
return $1 + '.';
});
console.log(str); // 2018.11.28
console结果:
$0:2018-
$1:2018
$2:-
$0:11-
$1:11
$2:-
2018.11.28
这里使用了 replace() 方法。
观察 Console 打印出来的结果,可以看出
$0 即是我们的正则 var re = /(\d+)(-)/g 去匹配 var str = "2018-11-28" 所得到的结果,
这里我们匹配成功了两次,即 2018- 及 11-;
$1 即是我们的一个小括号 (\d+) 的匹配结果,所以结果为 2018 以及 11;$2 即是我们的第二个小括号 (-) 的匹配结果,所以结果为 - 以及 -。
最后,我们做的事情就是,将 $1 加上 .,并返回最终结果给 str,最终结果:2018.11.28。
另一个例子:
var str = "abc";
var re = /(a)(b)(c)/;
console.log(str.match(re));
console结果:
["abc", "a", "b", "c", index: 0, input: "abc", groups: undefined]
2. 分组引用\n
分组引用的概念就是可以引用大正则中指定的小正则规则,例如:
var reg = /^([a-z])([a-z])\2([a-z])$/
// 符合的字符串:book week http ...
具体上面的例子理解为\2代表着第二个小正则规则的完全引用,就是和第二个小正则([a-z])一样,可以减少正则的复杂度和处理多次重复规则
4. 匹配字符 []
[] 这样的中括号的整体,代表一个字符。
字符串包含中括号中任一字符即满足条件
var reg = /^[a-zA_Z0-9_]$/
// 这个正则和等价于\w 就是匹配一个0~9或字母或_之间的一个字符
// 而正则[xyz]中的xyz分别代表a-z、A_Z、0-9,xyz只是一个代表标识,
// 可以有xyzhw各种组合
// 就像这个例子中有下划线_一样四个的匹配
// 有一个重点补充,在[]中的特殊元字符一般都代表本身含义,如下
var reg = /^[.?+&]$/
// 代表着匹配. .? ?+ ...等等
var str1 = "abcd";
var re1 = /a[bcd]c/;
console.log(re1.test(str1)); // true
var str2 = "abc";
var re2 = /a[^bcd]c/;
console.log(re2.test(str2)); // false
var str3 = "a.c";
var re3 = /a[a-z0-9A-Z]c/;
console.log(re3.test(str3)); // false
解析:
- /a/:匹配字母 a
- /[bcd]/:匹配字母 bcd 中的一位
- /[d]:匹配字母 d
- ^ 如果写在 [] 里面的话,就代表排除的意思。在这里就代表着 a 和 c 中间不能是 bcd 中的任意一个
- /[a-z0-9A-Z]/:匹配小写字母 a-z,或者数字 0-9,或者大写字母 A-Z。即 a 与 c 之间只能是上面匹配地上的字符。
5. 边界符\b
匹配一个单词边界,也就是指单词和空格间的位置(边界主要是单词的左右两边) 例如:
var reg = /er\b/
// 可以匹配never中的er,但是不能匹配verb中的er
var reg = /\b\w+\b/g
// 能匹配字母数字和下划线与单词边界 'my blog is www.ngaiwe.com'
// 能匹配 'my'、'blog'、'is'、'www'、'ngaiwe'、'com'
6. 只匹配不捕获 ?
下面举一个例子,但是涉及到捕获内容,如果同学们不太明白,可以先跳过此处,看完下面捕获,再返回来看
var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/g
var str = '110105199001220613'
console.log(reg.exec(str))
// 打印结果为 "110105199001220613", "110105", "1990", "01", "22", "1", "3"
var reg = /^(\d{6})(?:\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/g
// 打印结果为 "110105199001220613", "110105", "01", "22", "1", "3"
// 会将第二个小分组只匹配,不捕获
7. 正向肯定预查 ?=
这个概念比较难理解,用于就是为了匹配一个元素后面是的元素是否符合相应规则,但是并不消耗这个规则,例子1:
var reg = /windows(?=95|98|NT|2000)/
var str1 = 'windows2000'
var str2 = 'windowsxp'
console.log(reg.test(str1))
console.log(reg.test(str2))
// str1 为true str2 为false
console.log(reg.exec(str1))
console.log(reg.exec(str2))
// 能捕获到str1 并且捕获结果时windows 并没有将2000也同时捕获
// 说明正向预查只负责匹配相应规则
//-------例子2-----------
var reg1 = /win(?=d)dows/
var reg2 = /win(d)dows/
var str = 'windows'
console.log(reg1.test(str))
console.log(reg2.test(str))
// reg1 返回true reg2返回 false
// 原因是正向预查只负责匹配,不消耗字符,也就是并不会匹配为里面规则的字符
// reg1 相当于匹配windows并且符合win后面第一个出现的是d
// reg2 相当于匹配winddows
8. 正想否定预查 ?!
和正向肯定预查相反,匹配不符合规则的正则
9. \ 转义字符
将特殊元字符转换为普通字符,例:
var reg = /^2.3$/正常理解为匹配启示为2 结束为3中间是.的正则,但是在这里面.属于特殊元字符,意义是除了\n(换行符)以外的任意字符,所以不论是2.3/2+3/2s.3等等,只要是不·\n都匹配成功,所以为了这种需求就用到了转义字符\ 如下:var reg = /^2\.3$/将特殊元字符.转义为真正的.元素,再次匹配只有2.3才能匹配成功 如下思考:
var reg1 = /^\d$/
var reg2 = /^\\d$/
var reg3 = /^\\\d$/
var reg4 = /^\\\\d$/
首先reg1 表示0-9之间的数字 所以0-9都能匹配成功
reg2出现两个\ 不论是0-9 d \d都匹配失败,只有\d才匹配成功,
原因在于第一个转义字符把第二个\转义为普通\,
此时第一个\也表示普通字符,所以只有匹配到\\d才生效
reg3出现三个\,此时大家一定会认为\\\d才是正确答案,非也,
此时的正确答案是\[0-9]意思是\和0-9中任意一个数字,
原因在于第一个\将第二个转义,所以变为\\ \d分为了两部分,
\为普通字符,而\d表示一个0~9之间的数字,所以正确答案是\\[0-9]
reg4出现四个\ 很多同学会认为正确答案一定是\[0-9], 很可惜,
正确的是\\\\d,原因是当第一个把第二个转义为普通字符时,
第三个又把第四个转义为普通字符,所以最后匹配为\\\\d
看到这里相信有一部分小伙伴已经晕了,
虽然在工作我们不会玩这种操作,但是要深刻理解转义字符,
在正则中如果你直接写 var reg = /\/ 会报错,
因为正则中不能单独一个\出现,因为它是一个特殊元字符,
需要写至少两个, 例如: var reg = /^\\$/
正确的匹配结果为\\,所以牢记两个\代表真正的\,
到这里能搞明白的同学,相信转义字符已经完全掌握。
3. 量词
量词主要的作用是用来描述元字符出现的次数 如下:
+让前面的元字符出现一到多次?出现零到一次*出现零到多次{n}出现n次{n,}出现n到多次{n,m}出现n到m次
常用方法
JavaScript 正则默认: 正则匹配成功就会结束,不会继续匹配。如果想查找全部,就要加标识 g(全局匹配)
1. test()
规则:匹配字符串,匹配成功返回true,匹配失败返回false 语法:正则.test(字符串) 案例:
var str = "123abc";
var re = /\D/; // 匹配非数字
if(re.test(str)) {
console.log("不全是数字!");
} else {
console.log("全是数字!");
}
当test匹配到结尾或者匹配不到时,返回false, 成功则向数组添加当前小分组匹配第一个元素内容。 在RegExp的constructor中存在9,他们的具体指的是当前本次匹配小分组第一到第九捕获的内容
var reg = /\{([a-z]+)\}/g
var str = 'my name is {weiran}. I am from {china}'
var result = []
while (reg.test(str)) {
result.push(RegExp.$1)
}
console.log(result)
// ['weiran', 'china']
手动实现一个函数匹配到全部内容并且都能捕获到
这个方法当正则reg加了修饰符g 则返回大正则匹配到结果,如果没加g则返回exec捕获结果
var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/g
var str = '110105199001220613'
RegExp.prototype.myExec = function myExec() {
var str = arguments[0] || ''
var result = []
// 首先this指向的是RegExp,所以判断this是否加了全局修饰符g
// 如果没有,防止执行死循环,我们只执行一次exec并将其返回即可
if(!this.global) {
return this.exec(str)
}
var arrs = this.exec(str)
while(arrs) {
result.push(arrs[0])
// 此时lastIndex的值已经变为上一次的结尾
arrs = this.exec(str)
}
return result
}
2. search()
规则:匹配成功,返回成功的位置,失败返回-1 用法:字符串.search(正则) 案例:
var str = "abcdef";
var re1 = /d/i;
var re2 = /h/i;
console.log(str.search(re1)); // 3
console.log(str.search(re2)); // -1
3. match()
规则:匹配成功,返回匹配成功的数组,匹配不成功,返回 null 用法:字符串.match(正则) 案例:
var str = "123fadf321dfadf4fadf1";
var re = /\d+/g;
console.log(str.match(re)); //(4) ["123", "321", "4", "1"]
当加了修饰符g,返回的是大正则匹配结果组成的数组,
不加修饰符g则返回大正则和每个小分组返回结果组成的数组,
但是他也有局限性,就想上面说的在加了修饰符g的时候,会忽略小分组捕获内容,只捕获大正则捕获内容,解决办法就向上面myExec一样,将arrs[0]改为arrs,在每次匹配到结果时,将每个小分组也保存下来。
4. replace()
规则:匹配陈宫的字符串替换成新的字符串。 用法:字符串.replace(正则, 新的字符串) 案例:
var str = 'aaa';
var re = /a+/g;
str = str.replace(re, "b");
console.log(str); // b
敏感词替换
var s1 = '非诚勿扰在中国船的监视之下寸步难行';
var re = /非诚|中国船|监视之下/g;
s1.replace(re, function(str) {
return '*'.repeat(str.length);
})
替换大括号里的内容
var str = 'my name is {lalala}, I\'m from {haia}'
var reg = /\{([a-z]+)\}/
str = str.replace(reg, '123')
console.log(str)
// 打印出 my name is 123, I'm from {ngaiwe}
// 同学们会发现和exec的懒惰性很相似,不加修饰符g 只匹配第一个lastIndex没有改变
var reg = /\{([a-z]+)\}/g
// 打印出 my name is 123, I'm from 123
replace不会修改原始字符串
var str = 'my name is {weiran}, my blog is {ngaiwe}'
var reg = /\{([a-z]+)\}/g
str = str.replace(reg, function () {
console.log(arguments)
})
// 打印出当前匹配的小分组,如果函数中没有return出替换值,则返回undefined
5. split()
按照正则规则拆分数组
var str = 'weiRanNgaiWe'
var reg = /[A-Z]/
console.log(str.split(reg))
// ["wei", "an", "gai", "e"]按照大写拆分成数组
正则原型方法
RegExp.prototype正则原型对象上一共就三个方法,exec test和toString
exec用于捕获组而设计,实参是要匹配的字符串
var str = '234ewqe2r3562';
var reg = /\d+/;
reg.exec(str);
// ["234", index: 0, input: "234ewqe2r3562", groups: undefined]
// 0: "234"
// groups: undefined
// index: 0
// input: "234ewqe2r3562"
// length: 1
// __proto__: Array(0)
str = '文字';
reg.exec(str);
// null
捕获原理
- 在捕获的时候先验证当前字符串和正则是否匹配,不匹配返回null(没有捕获到任何内容)
- 如果匹配从字符串最左边开始,向右查找到匹配内容,并把匹配的内容返回
捕获结果
- 结果是一个数组
- 第一项0 是当前本次大正则中匹配的结果
- index是匹配到的结果在字符串中的索引位置
- input当前正则操作的原始字符串
- 如果大正则中有分组(),获取的数组中从第二项开始都是每个小分组的捕获结果 下面举一个身份证正则的例子 便于参考,具体里面匹配规则下面会单独介绍,这里只学习字段意义
var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;
var str = '110010199301032345'
reg.exec(str)
// 执行结果:
// ["110010199301032345", "110010", "1993", "01", "03", "4", "5", index: 0, input: "110010199301032345", groups: undefined]
// 0: "110010199301032345"
// 1: "110010"
// 2: "1993"
// 3: "01"
// 4: "03"
// 5: "4"
// 6: "5"
// groups: undefined
// index: 0
// input: "110010199301032345"
// length: 7
懒惰性
正则捕获存在懒惰性,在上面执行exec只捕获到第一个符合规则的内容,第二次执行也是捕获到第一个内容, 后面的内容无论执行多少次都无法捕获到。
解决办法:在正则末尾加修饰符
g(全局匹配)
原理
正则本身有lastIndex属性, 下一次正则在字符串中匹配查找的开始索引
默认值是0, 从字符串第一个位置开始查找,由此可见当执行完exec后lastIndex并没有变,
并且就算手动修改lastIndex也不会起作用
var str = '1w2q3e'
var reg = /\d+/
console.log(reg.lastIndex)
reg.exec(str)
console.log(reg.lastIndex)
reg.exec(str)
// 0
// 0
在正则表达式末尾加g后,每次执行exec后,浏览器默认会修改lastIndex。
下次从上一次结束的位置开始查找
reg = /\d+/g
console.log(reg.lastIndex) // 0
reg.exec(str)
console.log(reg.lastIndex) // 1
reg.exec(str)
reg.global可以判断正则是否是全局匹配
toString
将正则表达式转化为字符串
test
如上
正则解析
看一个简单的正则:^[a-z0-9_-]{6,12}$
- ^表示匹配字符串的开始位置
- [a-z0-9_-]表示字符串的开头可以为
a-z的字母,0-9的数字,_下划线,-连接符- [a-z] 表示匹配 a-z 中任意单个字母;
- [0-9] 表示匹配 0-9 中任意单个数字;
- [_] 表示匹配下划线;
- [-] 表示匹配连接符 -。 所以,将前面的连起来,[a-z0-9_-] 表示字符串可以包含数字、字母、_、- 这四种形式的字符串。
- {6, 12} 表示该字符串的长度为 6-12 位。
$表示结束标志,^表示开始
^与$同时使用,表示精确匹配。
综上:这个正则表达式的用途校验字符串只能包含小写字母,数字,下划线,连接字符,并且最长12位,最短6位。
小栗子🌰🌰🌰
var str = "Cheer for yourself";
var reg1 = /^Cheer/;
var reg2 = /yourself$/;
var reg3 = /for/;
console.log(reg1.test(str));
console.log(reg2.test(str));
console.log(reg3.test(str));
第一个判断该字符串是否以 Cheer 开头; 第二个判断该字符串是否以 yourself 结尾; 第三个判断该字符串是否包含 for。
-
身份证号 前6位是数字地区区号组成,然后四位是年,两位月,两位日和四位随机,倒数第二位单数男性,双数女性, 最后一位可能是大写X,所以根据这个规则的正则是
var str = '110105199109214237' var reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/ console.log(reg.exec(str)) // ["110105199109214237", "110105", "1991", "09", "21", "3", "7", index: 0, input: "110105199109214237", groups: undefined] -
邮箱 规则:
- @前面可能是数字、字母、下划线、-、.
- -和.不能相连在一起 /^\w+((-|\w+)|(.\w+))*/ 开头一定是数字,字母或下划线组成,后面的内容可能是-与数字字母下划线 或者.和数字字母下划线组成的0到多个字符
- @后面部分 首先一定是数字字母组成的多位字符 然后可能存在是.组成的邮箱后缀或者链接前方字符的.和- 最后肯定是.组成的邮箱后缀
var reg = /^\w+((-|\w+)|(\.\w+))*@[a-zA-Z0-9]+((\.|-)[a-zA-Z0-9]+)*\.[a-zA-Z0-9]+$/ var str = 'aaa@hotmail.com.cn' console.log(reg.test(str)) // true -
URL截取 获取url后的搜索参数 参数转化键值对和哈希值{key: 'value'}
需要分为两部分捕获,首先第一次捕获?后面的参数,第二次捕获#后面的hash值 首先匹配第一个,他的规则是匹配等号两边所以是/()=()/,并且匹配的是非?&=#的特殊字符,将他们保存在obj对象中 其次匹配hash,方法和第一个类似只是匹配#后面的部分
String.prototype.myQueryURLParameter = function myQueryURLParameter () {
var obj = {}
this.replace(/([^?&=#]+)=([^?&=#]+)/g, function () {
obj[arguments[1]] = arguments[2]
})
this.replace(/#([^?&=#]+)/g, function () {
obj['HASH'] = arguments[1]
})
return obj
}
编写验证规则最流行和最简单的方法就是正则表达式了,但唯一的一个问题是正则表达式的语法太隐晦了,让人蛋疼无比。很多开发者为了在项目中应用复杂的验证,经常要使用一些小抄来记住正则式的复杂语法和各种常用命令。
在这篇文章中,我将试图让大家明白什么是正则表达式,以及如何更轻松地学习正则表达式。
也许你是初学者,那以防万一,我先来讲讲什么是正则表达式吧:
正则表达式可以帮助我们更好的描述复杂的文本格式。一旦你描述清楚了这些格式,那你就可以利用它们对文本数据进行检索、替换、提取和修改操作。
下面有一个正则表达式的简单例子。第一步先要引入有关正则式的命名空间: using System.Text.RegularExpressions; 第二步就是用指定的正则式构建一个正则表达式对象,下面的正则式是用来搜索长度为10的a-z的英文字母: Regex obj = new Regex("[a-z]{10}"); 最后,根据正则式在指定数据中检索匹配项,如果匹配IsMatch方法就会返回true。 MessageBox.Show(obj.IsMatch(“shivkoirala”).ToString()); 3个重要的正则式命令
记住正则语法最好的办法就是记住这三样东西:Bracket(括号), caret(插入符号)和Dollars(美元符号)。
B
在正则表达式中有3种类型的括号
方括号 “[“和花括号“{“ 。
方括号"["内是需要匹配的字符,花括号"{"内是指定匹配字符的数量。
圆括号“(“ 则是用来分组的。
C 插入符号 “^” 表示正则式的开始。
D 美元符号“$” 表示正则式的结束。 现在你知道上面的3个语法后,你就可以写世界上任何一条验证规则了。比如下面的例子就很好的说明了上面3条正则语法是如何协调运作的。
注:上图有个错误,"()"应为"{}"
上面的这条正则式只能匹配a-z的英文字母,同样是在中括号中标明匹配范围。
花括号中则是标明匹配字符串的最小长度和最大长度。
最后为了让表达式更规则,分别在开头和结尾加上了插入符号"^"和美元符号"$"。
好了,现在我们就用上面的3条语法来实现一些正则表达式的验证规则吧。
检查用户是否输入了shivkoirala? shivkoirala 让我们开始第一个验证,输入的字符在a-g之间? [a-g] 输入的字符在a-g之间并且长度为3? [a-g]{3} 输入的字符在a-g之间并且最大长度为3最小长度为1? [a-g]{1,3} 我如何在匹配像91230456, 01237648那样的固定8位数? ^[0-9]{8} 如何验证像LJI1020那样的发票编号,前3个是字母剩余为8位长度的数字?
前三个是字母: ^[a-z]{3} 后面是8位长度的数字: [0-9]{8} 所以整个表达式为: ^[a-z]{3}[0-9]{7}$ 验证像INV190203 或 inv820830那样的前3位是不区分大小写的英文字母,剩余8位是数字。
在前面的表达式中只能匹配前3个是小写英文字母的发票编号,如果我们输入大写字母那就不能匹配了。所以为了确保前3个字母是不区分大小写的,我们就要用表达式^[a-zA-Z]{3}。 ^[a-zA-Z]{3}[0-9]{7}$ 我们可以验证简单的网址URL格式吗?
第一步:检查是否存在www: ^www. 第二步:域名必须是长度在1-15的英文字母: . [a-z]{1,15} 第三步:以.com或者.org结束: . (com|org) 让我们在来看看BCD(其实也就是上面说的3条基本语法)如何验证email格式。
第一步:email开始是长度在1-10的英文字母,最后跟一个"@": ^[a-zA-Z0-9]{1,10}@ 第二步:@后面是长度在1-10的英文字母,后面跟一个".": [a-zA-Z]{1,10}. 第三步:最后以.com或.org结束: .(com|org) 验证值在0-25的数字: ^(([0-9])|([0-1][0-9])|([0-2][0-5]))$ 验证格式为MM/DD/YYYY, YYYY/MM/DD and DD/MM/YYYY的日期: 步骤
正则式
描述说明
先来检查 DD. 首先DD的长度为1-29 ( 2月份) , 1-30 (月小) , 1-31 (月大) .
所以 DD 就是 1-9 或 01-09
[1-9]|0[1-9]
允许用户输入1-9或者01-09.
再为DD添加匹配10-19
[1-9]|1[0-9]
允许用户输入01-19.
再为DD添加匹配20-29
[1-9]|1[0-9]|2[0-9]
允许用户输入01-29.
i再为DD添加匹配30-31
[1-9]|1[0-9]|2[0-9]|3[0-1]
最后用户可以输入01-31.
再来匹配日期间的分隔符"/","-"
[/ . -]
允许用户输入日期分隔符.
MM也是类似的操作
[1-9]|0[1-9]|1[0-2]
让用户输入月份值01-12.
最后就是YY的操作
1[9][0-9][0-9]|2[0][0-9][0-9]
允许用户输入年份1900-2099. 最后DD/MM/YYYY格式的日期的正则表达式为: ^([1-9]|0[1-9]|1[0-9]|2[0-9]|3[0-1])- / .- / . YYYY/MM/DD格式的日期: ^(1[9][0-9][0-9]|2[0][0-9][0-9])- / .- / .$ 快捷命令
你也可以用以下的快捷命令来简化你的正则表达式: 实际命令 快捷命令
[0-9] d
[a-z][0-9][_] w
0次或多次发生 *
至少一次发生 +
0次或1次发生 ?