我们正在尝试扫描文件列表以查找密码。根据我们的要求,密码应包含带有特殊字符的字母数字。
请帮助我解释此regex不起作用的原因((w*)([$%*@#]+)(w+)){10,}
注:我将在Linux环境中使用此regex
匹配条件:
1) Minimum 10 character
2) Should contain 1 special character
3) Should contain 1 Numerical character
4) should contain 1 Alphabetic character
您的正则表达式首先匹配零个或多个单词字符(w*)
,然后匹配至少一个但可能多个特殊字符([$%*@#]+)
,然后匹配最少一个但也可能多个单词字母(w+)
。无论匹配什么,您都要尝试将完全相同的字符串匹配至少10次(...){10,}
。因此,例如,您可以有abc$%def
,它将与最外层的Paranthes相匹配,但要匹配完整的表达式,您需要将该字符串重复至少10次,就像这个abc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%defabc$%def
我怀疑这是你想要的:)
很难确切理解需求是什么,但看起来有几种可能性:
匹配一个由10个字符组成的字符串,这些字符是字母数字和某些特殊字符的混合物。这是一个非常简单的正则表达式,实现这一点的正则表达式可能如下:
[w$&*@#]{10}
上面的问题是,它不需要一个特殊的角色总是在场。
关键部分可能是,在一个精确为10位的密码中,必须至少有一个特殊字符。为了实现这一点,你可以做这样的事情:
w{0,9}[$&*@#][w$&*@#]+
它的工作原理如下——我们知道必须至少有一个特殊字符,并且我们知道密码有10个字符长。因此,最初可能存在0到9个连续的w
字符。在那之后,必须有一个特殊的字符。然后,在该特殊字符之后,可以有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
字符,然后是一个特殊字符,再是五个单词或特殊字符的情况。
您可能还想考虑在这种情况下,两阶段流程是否会更好地工作。你可以使用一个简单的不完美的例子,其中包括没有特殊字符的结果(我的第一个例子),然后查询结果集,只过滤确实包含至少一个特殊字符的密码。
关于确切的规则再详细一点肯定会有所帮助。
考虑到对规则的澄清,以及环境是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
其中Dollar$$NoNum
没有数字,NothingSpecial123
没有特殊字符,123#@#@123456
没有字母字符。
但是,我们可以通过使用pipe(|
)字符将许多grep命令链接在一起,过滤掉这些误报,并过滤掉没有所需属性的项。
例如,要筛选出不包含字母字符的项目,我们可以使用以下内容:
grep -E -o '[a-zA-Z0-9_$%*@#]{10,}' ./pass.txt | grep -E -v '^[^a-zA-Z]+$'
注意到我们在第一个grep中使用了-o,现在我们可以明确地通过以^
开头和以$
结尾来匹配密码的开始和结束。匹配本身是一个反转字符类([^.....]
),它将匹配方括号中未指定的任何文本。例如,[^a]
将匹配任何不是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命令的过滤输出输入到下一个过滤器,到最后,我们已经删除了所有的误报。