5

我对 Regex 还很陌生,只是刚开始在学校学习它。我得到了我的第一个任务,并且完成得相当好。

让我解释一下,这样我的代码才有意义......任务是让我的 .NET Regex Tester 通过文本搜索密码。这些密码不能包含任何空格(所以我使用\S了)不能以数字或下划线开头,所以我使用了(?m:^([^_|^0-9]{1}) Can't end on two different characters

(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>)

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

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

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

有人知道我该如何解决这个问题吗?

非常感激。

4

2 回答 2

1

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

我将从字符限制开始。

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

(?m)(?<!\S)\S{8,20}(?!\S)

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

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

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

现在我们添加一些限制:

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

(?m)(?<!\S)(?![0-9_])\S{8,20}(?!\S)

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

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

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

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

现在应该很好了。


现在到你的正则表达式:

(?m:^([^_|^0-9]{1})

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

(?m:^([^_|^0-9])

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

(?m:^[^_|^0-9])

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

(?m:^[^_0-9])

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

(?m:^[^_0-9 ])

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

(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>)

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

(?<finalTwo>\S)(?:\<finalTwo>)

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

(?=.*\d)

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

(\S*)

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

(?=\S*\d)(?m:^[^_0-9 ])(\S*)(?<finalTwo>\S)(?:\<finalTwo>)

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

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

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

于 2013-10-03T16:40:57.857 回答
0

以下情况如何:

^(?!^[^0-9]+$)[^0-9_].{5,17}(.)\1$

^: 字符串开头。

(?!^[^0-9]+$):通过确保密码不仅仅是非数字字符的组合来确保有数字。

[^0-9_]: 确保它以不是数字或下划线的东西开头。

.{5,17}: 匹配任意字符 5 到 17 次。

(.):匹配最后一个字符之前的字符,并将其捕获在第 1 组中。

\1:确保最后一个字符与前一个字符相同。

$: 字符串结束。

[^0-9_],(.)\1占用 3 个字符,这使得 5 个字符作为最小值.{5,17},因此51 作为最小边界,因此 17 作为上边界,总共最多 20 个字符。

正则表达式 101 演示

我知道演示使用 PHP,但这并不重要。

于 2013-10-03T16:23:27.670 回答