-1

我们正在尝试扫描文件列表以获取密码。根据我们的要求,密码应包含带有特殊字符的字母数字。

请帮我解释为什么这个正则表达式不起作用 ((\w*)([$%*@#]+)(\w+)){10,}

注意:我将在 Linux 环境中使用这个正则表达式

匹配条件:

1) Minimum 10 character
2) Should contain 1 special character 
3) Should contain 1 Numerical character
4) should contain 1 Alphabetic character
4

2 回答 2

0

您的正则表达式首先匹配零个或多个单词字符(\w*),然后是至少一个但可能是许多特殊字符([$%*@#]+),然后是至少一个但可能是多个单词字符(\w+)。无论匹配什么,您都将尝试匹配该完全相同的字符串至少 10 次(...){10,}。因此,例如,您可以使用abc$%defwhich 将匹配最外面的括号,但要匹配完整的表达式,您需要将该字符串重复至少 10 次,就像这样abc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%def

我怀疑这就是你所追求的:)

很难准确理解要求是什么,但看起来有几种可能性:

匹配由字母数字和某些特殊字符混合而成的 10 个字符的字符串。这是一个非常简单的方法,实现此目的的正则表达式可能如下:

[\w$&*@#]{10}

上述问题在于它不需要始终存在特殊字符。

关键部分可能是在恰好 10 位的密码中必须至少有一个特殊字符。为此,您可以执行以下操作:

\w{0,9}[$&*@#][\w$&*@#]+

其工作原理如下 - 我们知道必须至少有一个特殊字符,并且我们知道密码长度为 10 个字符。\w因此,最初可以有 0 到 9 个连续字符。之后,必须有一个特殊字符。然后,在那个特殊字符之后,可以是\w字符或特殊字符。然而,上面的正则表达式不强制 10 个字符的确切长度。

要获得确切的长度,您可能必须明确长度,这可能会开始变得混乱。例如:

(\w{9}[$&*@#]|\w{8}[$&*@#][\w$&*@#]{1}|\w{7}[$&*@#][\w$&*@#]{2}|\w{6}[$&*@#][\w$&*@#]{3}|\w{5}[$&*@#][\w$&*@#]{4}|\w{4}[$&*@#][\w$&*@#]{5}|\w{3}[$&*@#][\w$&*@#]{6}|\w{2}[$&*@#][\w$&*@#]{7}|\w{1}[$&*@#][\w$&*@#]{8}|[$&*@#][\w$&*@#]{9})

本质上,这里我们为表达式的特定部分的长度组合中的每一种组合使用了许多正则表达式——例如,\w{4}[$&*@#][\w$&*@#]{5}恰好匹配四个\w字符,然后是一个特殊字符,然后是五个单词或特殊字符。

您可能还想考虑在这种情况下两阶段过程是否会更好。您可以使用一个简单的不完美示例,其中包括没有特殊字符的结果(我的第一个示例),然后查询结果集以仅过滤确实包含至少一个特殊字符的密码。

关于确切规则的更多细节肯定会有所帮助。

于 2021-10-28T12:31:31.120 回答
0

鉴于对规则的澄清,并鉴于环境是 linux 并且我们正在使用 grep,这有助于提供更好的答案!:)

我现在解决这个问题的方法不是使用单个正则表达式。规则过于复杂,无法用一个简单的正则表达式优雅地解决。但是,这是一个很好的起点(假设源文件是 pass.txt):

grep -E -o '[a-zA-Z0-9_$%*@#]{10,}' ./pass.txt

-E 表示未启动的表示扩展的正则表达式,这本质上意味着更多的正则表达式功能,例如 {} 不再需要转义,因此无需所有额外的斜杠就更容易阅读。

-o 只返回文件的匹配部分,而不是返回整行。

请注意单引号的使用,这很有帮助,因为$双引号中的字符将被解释为变量名的开头。单引号表示它被视为文字。

上述正则表达式的缺陷是您将匹配许多误报,例如以下示例中的最后三个:

Password@1234
sffa##1233P
Moose**F00!d
Dollar$$01234
Dollar$$NoNum
NothingSpecial123
123#@#@123456

whereDollar$$NoNum没有数字,NothingSpecial123没有特殊字符,123#@#@123456也没有字母字符。

但是,我们可以通过使用竖线 ( ) 字符将许多 grep 命令链接在一起来过滤掉这些误报|,并过滤掉不具有必需属性的项目。

例如,要过滤掉不包含字母字符的项目,我们可以使用以下内容:

grep -E -o '[a-zA-Z0-9_$%*@#]{10,}' ./pass.txt | grep -E -v '^[^a-zA-Z]+$'

注意到我们在第一个 grep 中使用了 -o,现在我们可以通过以 开头和结尾来明确匹配密码的开头^和结尾$。匹配本身是一个反转字符类 ( [^.....]),它将匹配方括号中未指定的任何文本。例如,[^a]将匹配任何不是 NOT 的字符,例如a匹配b。在我们的示例中,我们匹配的不是字母字符。因为我们也在匹配密码的开头和结尾,如果我们匹配,那么我们知道我们这里有一个密码,它完全由非字母的文本组成,这违反了规则#4,因为它应该包含一个字母特点。

然而,这与我们想要的相反 - 这将找到没有字母字符的匹配项。Grep 相当有用地允许我们使用 -v 反转输出,这正是我们想要的。因此,上面的输出将过滤掉不包含字母字符的匹配项。

将相同的原则应用于其他规则,我们得到以下最终 grep 命令:

grep -E -o '[a-zA-Z0-9_$%*@#]{10,}' ./pass.txt | grep -E -v '^[^a-zA-Z]+$' | grep -E -v '^[^0-9]+$' | grep -E -v '^[^$%*@#]+$'

前一个 grep 命令的过滤输出馈送到下一个过滤器,到最后,我们已经删除了所有的误报。

于 2021-10-28T16:38:08.593 回答