一段验证字符串必须包含大小写字母和数字的正则表达式

http://topic.csdn.net/u/20080715/22/bacb749b-2f47-4552-8e9f-83099d5e0fe4.html

http://topic.csdn.net/u/20080716/22/80cdd418-a0e9-4e7e-8435-df6d4bc11c4a.html

感谢


使用正则表达式,以实现下面的功能:
1)不可以为空
2)允许含有特殊字符:! $ % & \ () - / ; < ? [] ^ {}
3)必须同时含有半角英文大写字母、半角英文小写字母以及半角数字
4)8文字以上,16文字以下



方案1:此方法能判断1,2,3 但4使用了第二个正则进行判断
public class T {
  public static void main(String[] args) {
    System.out.println(regexText("13a4C5fdsfiaf"));
    System.out.println(regexText("123"));
    System.out.println(regexText("A47c83"));
    System.out.println(regexText("ZA25$4783"));
    System.out.println(regexText("z457E{"));
    System.out.println(regexText("524754x1&#"));
    System.out.println(regexText("10248Zgk@"));
    System.out.println(regexText("102xfas44dsfdhd48Zgk@"));
  }

  public static boolean regexText(String value) {
    String all = "[\\p{Graph}]{0,}";
    StringBuilder b = new StringBuilder();
    b.append("(" + all + "[0-9]+" + all + "[a-z]+" + all + "[A-Z]+" + all + ")");
    b.append("|");
    b.append("(" + all + "[0-9]+" + all + "[A-Z]+" + all + "[a-z]+" + all + ")");
    b.append("|");
    b.append("(" + all + "[a-z]+" + all + "[0-9]+" + all + "[A-Z]+" + all + ")");
    b.append("|");
    b.append("(" + all + "[a-z]+" + all + "[A-Z]+" + all + "[0-9]+" + all + ")");
    b.append("|");
    b.append("(" + all + "[A-Z]+" + all + "[a-z]+" + all + "[0-9]+" + all + ")");
    b.append("|");
    b.append("(" + all + "[A-Z]+" + all + "[0-9]+" + all + "[a-z]+" + all + ")");
    return value.matches(b.toString()) && value.matches("[\\p{Graph}]{8,16}");
  }
}


输出为
true
false
false
false
false
false
true
false



火龙果 提供了更好的方法,
import java.util.regex.Pattern;
public class Test01 {
  public static void main(String[] args) {
    String[] strs = {
        "",
        "123",
        "A4783",
        "zA25$4783",
        "z4uu3j57E{",
        "524754x1&#",
        "10248Zgk@",
        "102xfas44dsfdhd48Zgk@",
        "xfAs!dsf5dh&doo",
        "xfAsmdsf5dhdoo"
    };
    // 限定条件
    final String C;
    // 允许出现的字符
    final String SPECIAL_CHAR = "[-A-Za-z0-9!$%&()/;<?{}\\[\\]^\\\\]";
    // 数量
    final String QUANTITY = "{8,16}";
    Pattern pattern = Pattern.compile(CONDITION + SPECIAL_CHAR + QUANTITY);
    for (String str : strs) {
      System.out.println(pattern.matcher(str).matches());
    }
  }
}
使用了预搜索/零宽度的缝隙匹配具体介绍为(?=.*[a-z]) 表示当前位置后面必须出现 .*[a-z] 的字符,这个可以理解为必须出现小写字母。或者可以理解为某一个字符间的缝隙必须满足的条件,这个仅仅作为条件判断并不能匹配任何字符,因为这属于非捕获组中的环视(lookarround)零宽度匹配。 举个大家常见的例子: 表达式:Win(?=XP) 现有字符串 WinXP 和 WinNT,在应用这个表达式时前者能与之进行匹配,为什么呢? 当匹配器指示到 (?=XP) 时,也就是在 n 字母后面的缝隙,这个缝隙必须满足的条件是:后面的字符必须是 XP,如果是的话,匹配成功,否则匹配失败。由于 (?=XP) 是匹配缝隙的,因此并不会把 XP 给匹配输出,而只输出了 Win 因此,这个表达式的语义可以看作是:找到后面为“XP”字符所有的 Win。

假如,我们把表达式写成 Win(?=XP)(?=NT) 这样的话,那么这个语义是:找出后面
为“XP”并且为“NT”字符所有的 Win 可以想象,这是个永远无法满足的匹配。(?=XP)(?=NT) 这个表示当前的缝隙必须同时满足的条件

把这个表达式再改一下,改成 Win(?=.*XP)(?=.*NT) 这个表示 Win 的后面必须出现XP 与 NT,位置和顺序都是无关的(这主要是 .* 的作用)。当然了这个表达式的效率是比较低的,得向后进行两次断言。 如果字符串是 WincbaXPabcNT 这个字符串,当匹配指示器走到 n 后面的缝隙时开始进行向后断言,首先对 .*XP 进行断言,很明显能将 cbaXP 匹配成功,这时第一个断言完成,再对 .*NT 断言,可以看出 cbaXPabcNT 能与其匹配成功,这时第二个断言完 成,因此表达式 Win(?=.*XP)(?=.*NT) 能对 WincbaXPabcNT 进行匹配。同理 WincbaNTabcXP 也是同样的效果。

如果能理解上面的这些,对于 (?=.*[a-z])(?=.*[A-Z])(?=.*\\d) 这个的理应该不会很难吧,这个只不过是必须同时满足三个条件。这个表达式在开始部分就进行断言,即索引为 0 的地方,也就是第一个字符的前面的缝隙,这个缝隙后面的字符必须满足 .*[a-z] .*[A-Z] .*\\d 三个条件,也就是说
必后面必须出现至少一个小写字母、至少一个大写母、至少一个数字至于表达式 2 的使用,也就是 [ ] 内字符的转义需要注意一下。 ^ 和 - 在 [ ] 结构的表达式中是有一定意义的。 [^abc] 表示除 abc 以外所有的字符,注意,这是放在最前面表示这个意思,如果改成 [a^bc] 这个仅表示 a ^ b c 四个字符。如果需要匹配 ^ 这个字符的话,千万不要把它放在第一个,如果一定要放在第一个的话,得使用转义符。- 在 [ ] 表示字符的范围,比如 [a-z] 表示 a 与 z 之间的 26 个字母[a-zA-Z] 这个表示 a-z 和 A-Z 的 52 个字母。使用范围得注意了,如果写成[z-a] 的话,在 Pattern.compile 编译表达式时会对范围进行检查,这时会产生异常,因此在使用 - 范围时,后面的 Unicode 值必须大于等于前面的 Unicode值。 如果要匹配“-”的话,尽量不要把 - 这个放在字符之间,可以放在 [ ] 的两边。比如 [-a-z] 这就能匹配 26 个小写字母和“-”了。当然了,我们也可以写成[a-z-A-Z] 这个可以匹配 52 字母和“-”,但是这样很不直观,我们宁愿写成[a-zA-Z-] 或者 [-a-zA-Z] 这样。
快乐渡过每一天,减肥坚持每一天