如何匹配一个模式与至少一个数字,一个小写,一个大写

时间:2016-09-09 07:14:37

标签: regex tcl expect

使用Expect如何检查给定输入是否至少有一个大写字母,至少一个小写字母和至少一个数字或“! - %#”? 对于输入字符串的最小数量为10的类似问题,有人回答

expect  ^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])([!-%#])*.{10,}$

由于我是Tcl和Expect的新手,有人可以解释一下上述代码是如何工作的吗? 如果我们删除{10,}以删除最低限制,为什么它不起作用?

1 个答案:

答案 0 :(得分:2)

删除限制(绑定)量词{10,}无法删除最小限制,您需要替换为*(至允许空字符串)或+(要求至少1):

expect  ^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9#?!@$%^&*-]).*$

或仅(因为expect不需要完整的字符串匹配):

expect  ^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9#?!@$%^&*-])

如果您需要将符号限制在前瞻中的符号,只需将.*替换为[a-zA-Z0-9#?!@$%^&*-]*

expect  ^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9#?!@$%^&*-])[a-zA-Z0-9#?!@$%^&*-]*$ 
                                                    ^^^^^^^^^^^^^^^^^^^^^

我也会在Tcl正则表达式中以一致的方式使用贪婪量词,尽管这对当前模式没有影响。

<强>详情:

  • ^ - 字符串开头
  • (?=.*[A-Z]) - 在任何0+字符之后必须有一个大写的ASCII字母
  • (?=.*[a-z]) - 在任何0+字符之后必须有一个小写的ASCII字母
  • (?=.*[0-9#?!@$%^&*-]) - 在任何0+字符之后必须有一个ASCII数字,或字符类中定义的任何特殊符号
  • .* - 任意0个字符,最多可达
  • $ - 字符串的结尾。

(?=...)构造被称为正向前瞻“坚持自己的立场”,即一旦执行它们就不会提升正则表达式索引。因此,3个前瞻将逐个执行检查,一旦其中一个返回false,整个匹配将失败。

注意:为了避免使用.*进行不必要的回溯,您可以应用对比原理(即在前瞻中使用相应的否定字符类):

^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=[^0-9#?!@$%^&*-]*[0-9#?!‌​@$%^&*-])[a-zA-Z0-9#‌​?!@$%^&*-]*$

[^A-Z]*将匹配大写ASCII字母以外的一个或多个字符,[^a-z]*将匹配小写ASCII字母以外的一个或多个字符,等等。.*抓取整个字符串首先,然后回溯,检查后续子模式是否匹配。因此,否定的字符类更有效,并且可以更快地找到或失败匹配。