technology-note/其他各种/4.正则表达式在密码匹配中的使用.md
2019-04-02 14:27:37 +08:00

60 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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,}$
```