我想到了:
re.findall("([a-fA-F\d]*)", data)
但这种方法并不是很可靠,有没有更好的方法来获取所有MD5哈希代码?
既然MD5只是由32个十六进制数字组成的字符串,那么你可以向你的表达式中添加一个检查"32位数字"的条件,类似于这样:
re.findall(r"([a-fA-F\d]{32})", data)
[0-9a-f]{32}
会更好。 - enchance^[a-fA-F\d]{32}$
。 - toringere.compile(r'[0-9a-f]{32}', re.IGNORECASE)
。 - NuclearPeon在使用Python中的正则表达式时,几乎总是应该使用原始字符串语法r"..."
:
re.findall(r"([a-fA-F\d]{32})", data)
这将确保字符串中的反斜杠不被正常的Python转义所解释,而是直接传递给re.findall
函数,以便它可以按原样查看\d
。在这种情况下,你很幸运\d
没有被Python转义解释,但像\b
这样的字符(在Python转义和正则表达式中具有完全不同的含义)就会产生问题。re
模块文档。以下方法优于其他解决方案:
re.findall(r'(?i)(?<![a-z0-9])[a-f0-9]{32}(?![a-z0-9])', data)
这确保了匹配必须是一个由32个十六进制数字字符组成的字符串,但不包含在其他字母数字字符的更大字符串中。 对于所有其他解决方案,如果有37个连续的十六进制字符的字符串,该模式将匹配前32个字符并将其视为匹配项;或者如果有64个十六进制字符的字符串,则会将其分成两半并将每一半作为独立的匹配项。通过先行断言和后行断言来排除这些情况,它们是非捕获的,不会影响匹配结果的内容。
请注意,(?i)标志会使模式对大小写不敏感,这可以节省一点打字时间,而将整个模式用括号括起来是多余的。
以下是一个相对严谨的表达:
r"\b([a-f\d]{32}|[A-F\d]{32})\b"
但是如果这还不够好,因为你知道得到全数字的MD5校验和的概率只有3402823分之一,获得全字母数字的MD5校验和的概率为42万亿分之一,那么我们应该对这些有效的校验和说FU,也不接受任何不是字母数字的内容:
r"\b(?!^[\d]*$)(?!^[a-fA-F]*$)([a-f\d]{32}|[A-F\d]{32})\b"
00000000000000000000000000000000 # not MD5
01110101001110011101011010101001 # not MD5
ffffffffffffffffffffffffffffffff # not MD5
A32efC32c79823a2123AA8cbDDd3231c # not MD5
affa687a87f8abe90d9b9eba09bdbacb # is MD5
C787AFE9D9E86A6A6C78ACE99CA778EE # is MD5
please like and subscribe to my # not MD5
是的,我在工作中感到非常无聊。
r"\b[a-f\d]{32}\b|\b[A-F\d]{32}\b"
更好。 - Adam Smith由于MD5是由32个十六进制字符组成的,有时哈希值会用小写字母表示,因此还应考虑它们。
以下示例已针对四个不同的字符串进行测试:
900e3f2dd4efc9892793222d7a1cee4a
AC905DD4AB2038E5F7EABEAE792AC41B
900e3f2dd4efc9892793222d7a1cee4a900e3f2dd4efc9892793222d7a1cee4a
900e3f2dd4efc9892793222d7a1cee4a4a4a4
validHash = re.finditer(r'(?=(\b[A-Fa-f0-9]{32}\b))', datahere)
result = [match.group(1) for match in validHash]
if result:
print "Valid MD5"
else:
print "NOT a Valid MD5"
那么对于需要32个字符的"([a-fA-F\d]{32})"怎么样?
r
:c = r"[a-fA-F\d]"; re.findall(r"(?<!%s)(?:%s){32}(?!%s)" % (c,)*3, data) - jfs(c,)*3
应该被替换为(c,c,c)
。 - jfs