[id]: 8b08c4c0d6c111e8aa858b6a40460626
##一、背景

&emsp;&emsp;今天领导让我写几个正则表达式来对密码做强度验证，听到写正则表达式内心是这样的感觉（哈哈，三分钟搞定，今天又可以打鱼了）。需求如下：密码组成只能是**数字**，**字母**，**英文可见半角符号**，然后需要如下4个表达式:

- 长度6位及以上
- 长度6位及以上，包含数字，包含字母
- 长度6位及以上，包含数字，包含字母，包含半角符号
- 长度六位及以上，包含数字，包含大写字母，包含小写字母，包含半角符号

&emsp;&emsp;看完需求我就有点懵了，包含数字或者字母我会写，但是同时存在还要在一个表达式中就有点懵了。

##二、解决方法

&emsp;&emsp;以第三种为例，这个可以分解为如下需求：

- 存在数字
- 存在字母
- 存在半角符号
- 长度六位及以上

关键是如何同时满足前三个条件，在我有限的知识里并不知道怎么搞，然后只好求助于万能的百度了，最终在找了几个小时后发现如下几个关键词，来源[菜鸟教程](http://www.runoob.com/java/java-regular-expressions.html) ：

- (?=*pattern*) ：正向预测先行搜索

  名字看着高大上，不明所以，看完示例大概明白什么意思，这个表达式匹配从这个表达式起始的字符串（我也不知道咋解释），就是假设这样一个表达式abc(?=[abc]) ,用它来匹配abc123字符串，(?=[abc])只会对作用于后面的123，这个显然是不匹配的后整个就不匹配了，然后关键来了名字里有**预测**两个字，这两个字表名了这个表达式的特性：不占用字符，匹配后如果匹配成功就继续匹配了好像从来不存在这个东西一样，匹配失败就立即返回失败了。利用这个特性我们就可以给正则加限制条件了。

- (?!*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,}$
```

