我正在尝试在 AWS 云形成模板中输入一些密码条目。并将密码限制为字母数字字符和特殊字符的子集。我尝试了以下方法:
"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#@$?]).{8,}$"
这表明应该至少有一个小写和大写字母以及一个数字。另外,将特殊字符集限制为[#@$?]
我观察到,任何特殊字符(如果是最后一个字符)都是允许的。在其他任何地方都按预期被禁止
因此,Hello*E1
不允许但HelloE1*
允许。
如何禁止所有特殊字符,无论[#@$?]
它们出现在何处?
另外,如何禁止整个特殊字符集?"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$
没有帮助。这允许所有特殊字符。
任何帮助表示赞赏。
答案1
正则表达式:
^(?=[a-zA-Z0-9#@$?]{8,}$)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9]).*
解释:
在您提供的正则表达式中,前瞻用于确保您的字符串满足某些特定条件,但它们并不是阻止不需要的字符串的真正过滤器。您指定了以下条件:
(?=.*?[A-Z])
:至少匹配一个大写字母。(?=.*?[a-z])
:至少匹配一个小写字母。(?=.*?[0-9])
:至少匹配一个数字。(?=.*?[#@$?])
:至少匹配以下字符之一:#@$?
.{8,}
:匹配任意字符至少8次。
但至少有两个缺陷:
该
(?=.*?[#@$?])
部分是不必要的,因为这些特殊字符是可选的,而不是强制的[1]。正如我之前所说,您没有指定真正的过滤器,因此由于该
.{8,}
部分,您的正则表达式将接受任何字符串,只要它满足先行建立的条件,即使它具有不需要的特殊字符[1]。
因此,要解决这些缺陷,有必要:
删除该
(?=.*?[#@$?])
部分。添加一个新的前瞻,充当上面提到的过滤器。
要构建此过滤器,您应该考虑“我想要允许哪些字符?”而不是“我想禁止哪些字符?”,因为在这种特定情况下这是更容易处理的情况。如果您说您只想a-z
、A-Z
、0-9
和#@$?
成为允许的字符,那么前瞻应该如下所示:
(?=[a-zA-Z0-9#@$?])
但是,嘿,在这一步中,您甚至可以设置最小长度并告诉前瞻从哪里开始和在哪里停止(在本例中是字符串的开头和结尾):
(?=[a-zA-Z0-9#@$?]{8,}$)
我^
在这里省略了,因为它已经处于一切的开始,所以没有必要是多余的。现在我们只需将所有前瞻集合在一起并使用以下命令.*
来匹配有效密码.{8,}
:
^(?=[a-zA-Z0-9#@$?]{8,}$)(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9]).*
笔记:
- 虽然,在您提供的正则表达式和示例中,我真的不知道为什么:1)
#@$?
没有被视为强制性的; 2) 不需要的字符只允许出现在字符串的末尾,而不能出现在其他地方。也许这与AWS使用的正则表达式引擎有关,因为当我自己测试它时,一切都按预期工作。
答案2
我们希望针对每个所需的字符类型以及长度要求,在字符串开头锚定一个前瞻。然后简单地.*
把它全部吞掉:
^(?=[0-9a-zA-Z#@\$\?]{8,}$)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])(?=[^0-9]*[0-9]).*
解释:
首先,我决定在匹配所需的 char 类型(例如一个大写)时避免使用惰性量词,原因如下:
- 它们是昂贵的。
- 不同的正则表达式引擎有不同的表示惰性的方式。 (有一对夫妇根本不支持。)
- 它们不像替代方案那么常见/熟悉。
因此,为了提高效率、可读性和“可移植性”,我使用了该^[^x]*[x]
结构。
现在把剩下的分解...
^
: 一切都从头开始
(?=[0-9a-zA-Z#@\$\?]{8,}$)
:在字符串开头和结尾之间使用 8 个或更多允许的字符进行前瞻。
接下来的三个使用相同的模式:匹配零个或多个字符的前瞻不是匹配所需的字符,然后匹配所需的字符。这些都锚定在开头,因此效果是允许在字符串中的任何位置匹配所需的字符:
(?=[^a-z]*[a-z])
: 至少一个小写字母。
(?=[^A-Z]*[A-Z])
: 至少一个大写字母。
(?=[^0-9]*[0-9])
:至少一位数字。
.*
:上面的所有内容都是向前看的,不会消耗任何东西,所以在这里消耗掉所有东西。第一个前瞻确保整个字符串是有效的字符,因此这是安全的。
我没有声称这是优化的(除了避免惰性量词)。这只是更容易理解的形式之一。
注意:您观察到的问题的原因#@$?
是由于前瞻未锚定到字符串末尾。任何字符将在这四个字符之一之后匹配(不一定只是在最后一个位置)。当然,您不能只是添加,$
因为这样会排除有效字符。这就是为什么我在同一个前瞻中包含所有有效字符。
答案3
你的正则表达式没有禁止任何字符,它只是需要每个类都有一个实例。要限制允许的字符,请更改您的.
(这意味着任何字符)到允许的字符集:
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#@$?])[a-zA-Z0-9#@$?]{8,}$
请注意,如果这意味着是一个perl
字符串,则需要转义$
s 和@
s 或使用强引号('...'
或q{...}
)。您还需要确保正则表达式在 ASCII 模式下工作(a-z
仅匹配英文字母,并.
匹配任何字节)。
(?=.*?[#@$?])
如果不这样做,请删除要求至少其中一个符号。