technology-note/其他/4.正则表达式在密码匹配中的使用.md

60 lines
2.8 KiB
Markdown
Raw Permalink Normal View History

2022-02-23 16:59:03 +08:00
---
id: "2018-09-30-10-58"
date: "2018/09/30 10:58"
title: "正则匹配之正向/反向预测先行搜索"
tags: ["java","正则匹配","pattern","预测先行搜索"]
categories:
- "java"
- "正则匹配"
---
## 一、背景
  今天领导让我写几个正则表达式来对密码做强度验证,听到写正则表达式内心是这样的感觉(哈哈,三分钟搞定,今天又可以打鱼了)。需求如下:密码组成只能是**数字****字母****英文可见半角符号**,然后需要如下 4 个表达式:
- 长度 6 位及以上
- 长度 6 位及以上,包含数字,包含字母
- 长度 6 位及以上,包含数字,包含字母,包含半角符号
- 长度六位及以上,包含数字,包含大写字母,包含小写字母,包含半角符号
  看完需求我就有点懵了,包含数字或者字母我会写,但是同时存在还要在一个表达式中就有点懵了。
## 二、解决方法
  以第三种为例,这个可以分解为如下需求:
- 存在数字
- 存在字母
- 存在半角符号
- 长度六位及以上
关键是如何同时满足前三个条件,在我有限的知识里并不知道怎么搞,然后只好求助于万能的百度了,最终在找了几个小时后发现如下几个关键词,来源[菜鸟教程](http://www.runoob.com/java/java-regular-expressions.html)
- (?=_pattern_) :正向预测先行搜索
名字看着高大上,不明所以,看完示例大概明白什么意思,这个表达式匹配从这个表达式起始的字符串(我也不知道咋解释),就是假设这样一个表达式 abc(?=[abc]) ,用它来匹配 abc123 字符串,(?=[abc])只会对作用于后面的 123这个显然是不匹配的后整个就不匹配了然后关键来了名字里有**预测**两个字,这两个字表名了这个表达式的特性:不占用字符,匹配后如果匹配成功就继续匹配了好像从来不存在这个东西一样,匹配失败就立即返回失败了。利用这个特性我们就可以给正则加限制条件了。
<!-- more -->
- (?!_pattern_) :反向预测先行搜索
概念和上面一样但是效果是相反的abc(?![abc]),对于 abc123 是匹配成功的,对于 abca 匹配失败,如下所示:
```javascript
reg = /abc(?![abc])/;
reg.test('abc123');
//返回true
reg.test('abca');
//返回false
```
&emsp;&emsp;有了上面的知识就能搞定需求啦。
## 三、结果
&emsp;&emsp;对于存在字母我们可以用这样的表达式`(?=.\*?[a-zA-Z]+.\*?),来检查是否存在至少一个字母,最后对于需求 3 的表达式如下:(半角字符我用的 ASCII 码里的 16 进制表示的)
```javascript
^(?=.*?\d+.*?)(?=.*?[a-zA-Z]+.*?)(?=.*?[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+.*?)[\da-zA-Z\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]{6,}$
```