之前在 edabit 做练习时遇到题目
搜了文章
(pattern) : 分组匹配()中的正则pattern 匹配并获取这一匹配结果,所获取的匹配可以从产生的 Matches 集合得到。
(?:pattern) :分组匹配中?:后的正则 pattern 匹配但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。
查看下面的执行结果(y)分组匹配,中匹配了y,并在集合中存储了分组匹配的结果
var reg =/industr(y)/
var str="industry abc"
str.match(reg);
查看结果 ['industry', 'y', index: 0, input: 'industry abc', groups: undefined]
查看(?:y)执行结果匹配了,没有存储结果
var reg =/industr(?:y)/
var str="industry abc"
str.match(reg);
查看结果 ['industry', index: 0, input: 'industry abc', groups: undefined]
(?=pattern) :正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。预查不消耗字符,也就是说,在一个匹配发生后,在匹配完之后,继续后面匹配时,还是从匹配开始的地方往后匹配,而不是从包含预查的字符之后开始。
var reg =/industr(?=y)(y abc)/
var str="industry abc"
str.match(reg);
// 输出 ['industry abc', 'y abc', index: 0, input: 'industry abc', groups: undefined]
可以看到输出结果中含有'y abc' 为什么能匹配成功呢,(?=y)不消耗字符,匹配完后,后面还是从"industry abc" 中的y abc 开始后面的匹配
共同点
(?:pattern) 与 (?=pattern)都匹配pattern,但不会把pattern结果放到Matches的集合中,即Matcher.group()不会匹配到(?:pattern)与(?=pattern)
区别
-
(?:pattern)匹配得到的结果包含pattern,(?=pattern)则不包含。如:对字符串:"industry abc"的匹配结果:var reg =/industr(?:y)/ var str="industry abc" str.match(reg); 输出:["industry", index: 0, input: "industry abc", groups: undefined]
var reg =/industr(?=y)/ var str="industry abc" str.match(reg); ["industr", index: 0, input: "industry abc", groups: undefined]
是否消耗字符
(?:pattern) 消耗字符,下一字符匹配会从已匹配后的位置开始。
(?=pattern) 不消耗字符,下一字符匹配会从预查之前的位置开始。
即后者只预查,不移动匹配指针。如:
下面在来个题目巩固一下:
题目1:
创建一个特殊的正则表达式,以检测GET请求是否有效。
字符串的格式如下:
name1=val1&name2=val2&name3=val3&name4=val4
您需要使用四个名称检测请求:“ val”,“ id”,“ desc”,“ time”(每个值可以具有不同的顺序)。
例如:
"val=val1&id=val2&desc=val3&time=val4"
"id=val2&val=val1&time=val4&desc=val3"
每个名称都有一个特定的值:
- val 可以包含字符串a到z和数字0到9(任何情况下都可以接受)
- id 是从0到10的数字
- desc 可以包含字符串a到z
- 时间 是格式化值(00:00到99:99)
例如:
str="val=test1151&id=5&desc=helloWorld&time=54:33"
str="id=10&val=123test&time=99:00&desc=itsok"
答案:
const regExp = /(?=.*&?desc=([a-zA-Z]+)(?:&\w|$))(?=.*&?val=([a-zA-Z0-9]+)(?:&\w|$))(?=.*&?time=(\d{2}:\d{2})(?:&\w|$))(?=.*&?id=(10|[0-9])(?:&\w|$))^[^&][^-]*[^&]$/;
function dataRegexLovely(str) {
var m = str.match(regExp);
return {
desc: m[1],
val: m[2],
time: m[3],
id: +m[4]
};
}
题目2:
密码校验
-
要求6~12位
-
必须包含数字,小写字母,大写字母,特殊字符($@,_.)之一
根据要求先匹配数值正则:
密码是 var str="123abc32";
/^(?=.*\d).*$/
var reg=/^(?=.*\d).*$/;
reg.test(str)
输出:true
上面可以保证密码中含有数字,然后添加包含大小字母
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/
var str="123abcA32";
var reg=/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/;
reg.test(str)
输出:true
在添加特殊字符
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[$@,_.]).*$/
var str="123abcA$32";
var reg=/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[$@,_.]).*$/;
reg.test(str)
输出:true
是不是感觉就完成了,根据这个匹配规则,只能保证从字符前到后里面包含了需要的字符,不能保证多出哪些字符,比如其中含有--
var str="123abcA$--32";
var reg=/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[$@,_.]).*$/;
reg.test(str)
输出:true
再次改进: 根据上面的学习(?=pattern)是不消耗字符的,.*$/这部分才是完成消耗字符的
对完成消耗字符限制,只能含有需要字符就可以
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[$@,_.])[\da-zA-Z$@,_.]{6,12}$/
/^[\da-zA-Z$@,_.]{6,12}$/ 完成字符消耗只能是[\da-zA-Z$@,_.]这些字符
匹配html 标签 var reg=/(?:<)([a-z1-9]+)[^<>/]*(?:>)/g;