验证密码的最小/最大长度

use*_*457 5 .net regex

我是Regex的新手,刚开始在学校学习它.我得到了我的第一个任务,并且相当顺利.

让我解释一下,我的代码是有道理的...分配是让我的.NET Regex Tester通过文本搜索密码.这些密码不能包含任何空格(所以我用过\S)不能以数字或者下划线开头,所以我用的是(?m:^([^_|^0-9]{1}) 不能以两个不同的字符结束

(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>)
Run Code Online (Sandbox Code Playgroud)

必须包含至少一个数字,所以我使用了前瞻.现在,问题在于,代码现在是一个非常混乱的事情.

(?=.*\d)(?m:^([^_|^0-9]{1})(\S*)(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>))
Run Code Online (Sandbox Code Playgroud)

我还要添加一件事,密码长度必须在8到20个字符之间.我知道我必须使用{8,20}(我认为),但问题是,无论我在哪里输入它,它都完全杀死了搜索.

有没有人知道如何解决这个问题?

非常感激.

Jer*_*rry 1

[免责声明,这是一个很长的答案!]

我将从字符限制开始。

您必须使用(?<!\S)(?!\S)来指示密码的开头和结尾,并使用\S{8,20}来表示实际密码:

(?m)(?<!\S)\S{8,20}(?!\S)
Run Code Online (Sandbox Code Playgroud)

正如您可能已经知道的(?m)那样,它用于多行(^$分别匹配行的开头和结尾,而不是此模式下的字符串)。

(?<!\S)确保密码前没有非空白字符。

(?!\S)确保密码后没有非空白字符。

现在我们添加一些限制:

不能以数字或下划线开头:(?![0-9_])密码开头的负向前瞻:

(?m)(?<!\S)(?![0-9_])\S{8,20}(?!\S)
Run Code Online (Sandbox Code Playgroud)

必须至少包含一位数字:(?=\S+[0-9])密码开头的正向前瞻:

(?m)(?<!\S)(?![0-9_])(?=\S+[0-9])\S{8,20}(?!\S)
Run Code Online (Sandbox Code Playgroud)

必须以相同的字符结尾:您必须捕获倒数第二个字符并使用反向引用。您可以将此\S{8,20}部分更改为:\S{6,18}(\S)\1

(?m)(?<!\S)(?![0-9_])(?=\S+[0-9])\S{6,18}(\S)\1(?!\S)
Run Code Online (Sandbox Code Playgroud)

现在应该很好了。


现在到你的正则表达式:

(?m:^([^_|^0-9]{1})
Run Code Online (Sandbox Code Playgroud)

首先,{1} 是多余的,因为如果删除它,它根本不会改变任何内容。

(?m:^([^_|^0-9])
Run Code Online (Sandbox Code Playgroud)

其次,括号不平衡。不知道那应该是什么,但我猜第一个括号不是故意的。

(?m:^[^_|^0-9])
Run Code Online (Sandbox Code Playgroud)

接下来,字符类[^_|^0-9]匹配除_|^范围之外的任何字符0-9。我确信密码可以|以或开头^。元字符|在字符类中失去了意义!你可以使用这个:[^_0-9]代替,这将变成:

(?m:^[^_0-9])
Run Code Online (Sandbox Code Playgroud)

可以使用它,但您必须记住这是密码中的第一个字符;因为您需要尊重的字符范围为 8 到 20 个字符,而它只是更改为 7,19。唯一剩下的就是它也接受一个空格。您可以在角色类中放置一个来避免这种情况:

(?m:^[^_0-9 ])
Run Code Online (Sandbox Code Playgroud)

好的,现在看起来好多了,下一张:

(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>)
Run Code Online (Sandbox Code Playgroud)

首先是一个命名的捕获组,好吧,还有一个启用了不区分大小写模式的非捕获组(不是很有必要,因为我们在正则表达式中没有任何字母)并且\S{1}位于该非捕获组内。再说一遍,这{1}是多余的。删除它和(?i)模式,这变成:

(?<finalTwo>\S)(?:\<finalTwo>)
Run Code Online (Sandbox Code Playgroud)

这还不错,如果它匹配最后两个字符,它确实可以工作。

(?=.*\d)
Run Code Online (Sandbox Code Playgroud)

效果很好。您可能想要寻找除匹配项之外的字符0-9\d但如果您不介意,这几乎可以工作;最好使用\S而不是.在这里使用,以防文本中存在两个由空格分隔的密码,这可能会使事情不像您预期​​的那样。

(\S*)
Run Code Online (Sandbox Code Playgroud)

这部分或多或少还可以。只是没有施加任何限制。

(?=\S*\d)(?m:^[^_0-9 ])(\S*)(?<finalTwo>\S)(?:\<finalTwo>)
Run Code Online (Sandbox Code Playgroud)

好的,现在,记住(?m:^[^_0-9])需要一个字符,然后(?<finalTwo>\S)(?:\<finalTwo>)需要两个字符,总共 3 个字符。因此您施加的限制是:

(?=\S*\d)(?m:^[^_0-9 ])(\S{5,17})(?<finalTwo>\S)(?:\<finalTwo>)
Run Code Online (Sandbox Code Playgroud)

它几乎可以工作,你只需要添加一些东西来防止较长密码的部分匹配。您通常可以使用单词边界\b,但没有提到任何有关符号的内容,因此更安全的做法是假设也允许使用类似的密码$@4*&AUn++,而这就是单词边界失败的地方。这就是为什么我建议使用否定环视。