Python 正则表达式匹配字母表中的 3 个连续字符,但不一定并排
Python regex to match 3 consecutive characters in the alphabet but not necessarily side by side
我必须构建一个 python 函数,该函数使用正则表达式来检查密码的复杂性,该密码应至少包含 8 个字符,包含数字、字母和特殊符号以及最后的规则(最难的):不是包含三个连续的字母或三个连续的数字。
为了说明最后一条规则:Mz2a%yc98B
将不被接受,因为它包含 3 个连续的字母:aBc
前两条规则我做得很好,但我不知道我能为最后一条规则做些什么。我认为这很复杂。有些人告诉我使用正则表达式不可能做到这一点,但实际上它必须是可能的,否则这很疯狂不?
非常感谢!
到目前为止我的代码:
import re
pattern = re.compile(r"")
while True:
password = input("Enter your password")
if re.match(r"(?=.*[a-z])(?=.*[A-Z])(?=(.*[!%@$#&^*()\-__+.]){1,})(?=.*[0-9]).{8,}", password):
result = pattern.match(password)
print("Your password is strong enough")
else:
print("Your password is not strong enough")
而且在我给出的示例密码中,是的,它们是 aBc,B 是最后一个字符。
这只是一个例子。当我指的是连续的时,我指的是字母表中的连续。例如,如果使用甚至散布在密码中的 efg 字母,它必须检测到它。
谢谢
这里是你的问题集的第三个标准的解决方案。
import string
from more_itertools import windowed
alphabet = string.ascii_lowercase
numbers = string.digits
passwords = ["Mz2a%yc98B", "a1b2g3D!", "Tr0ub4dor?"]
def find_triplets(charset: set, target: str) -> bool:
if len(charset) < 3:
return False
else:
chars = "".join(sorted(charset))
triplets = ["".join(tpl) for tpl in windowed(chars, 3)]
return any(triplet in target for triplet in triplets)
for pwd in passwords:
# we use sets to get rid of duplicatess
alpha = set()
nums = set()
for char in pwd:
if char.isalpha():
alpha.add(char.lower())
elif char.isdigit():
nums.add(char)
else:
pass # we don't care about symbols here
if find_triplets(alpha, alphabet) or find_triplets(nums, numbers):
print(f"Your password {pwd} contains 3 consecutive letters or numbers")
else:
print(f"Your password {pwd} is good enough, I guess")
在设置代码之后,我们首先定义一个函数,在输入 charset
被排序并变成字符串后,生成 3 个字符的字符串 (triplets
)。这使用 windowed()
function from the very helpful 3rd party more_itertools
模块。如果函数 returns True
找到与 target
字符串中的连续序列匹配的任何三元组,则函数 False
如果没有。够简单了。
接下来,我们遍历我们的密码列表(您在代码中使用了 input()
,这很好)。首先,我们逐个字符地遍历密码字符串,并将它们添加到适当的集合中(在字母字符的情况下为小写)。然后我们调用我们的 find_triplets()
函数来测试字母或数字的连续运行,并相应地打印一条消息。
您显然想要更改其中的一些内容以适应您的任务,但我会把它留给您。
还有另一种使用 re.search()
的方法,但我认为 any(triplet in target for triplet in triplets)
更加 Pythonic。
你问用正则表达式可能吗?当然!漂亮吗?那是在旁观者的眼中。
您需要一个如下所示的正则表达式(设置了 case-indifferent 标志):
^(?=.*\d)(?=.*[a-z])(?=.*[<special symbols here>])(?!<no 3 digits that are consecutive>)(?!<no three letters that are consecutive>).{8}
让我们看看负面前瞻
(?!<no 3 digits that are consecutive>)
我们可以这样写。
(?!(?:(?=.*0)(?=.*1)(?=.*2))|(?:(?=.*1)(?=.*2)(?=.*3))|(?:(?=.*2)(?=.*3)(?=.*4))|(?:(?=.*3)(?=.*4)(?=.*5))|(?:(?=.*4)(?=.*5)(?=.*6))|(?:(?=.*5)(?=.*6)(?=.*7))|(?:(?=.*6)(?=.*7)(?=.*8))|(?:(?=.*7)(?=.*9)(?=.*9)))
表达式可以写成 verbose 模式(re.X
或 re.VERBOSE
)使其成为 self-documenting.
(?! # begin negative lookahead
(?: # begin non-capture group
(?=.*0) # match > 0 characters followed by 0 (positive lookahead)
(?=.*1) # match > 0 characters followed by 1
(?=.*2) # match > 0 characters followed by 2
) # end non-capture group
| # or
... similar for (?:(?=.*1)(?=.*2)(?=.*3))
...
) # end negative lookahead
构建
(?!<no three letters that are consecutive>)
与 x
、y
和 z
相似(包含 23 个元素的交替,a
、b
和 c
).
我必须构建一个 python 函数,该函数使用正则表达式来检查密码的复杂性,该密码应至少包含 8 个字符,包含数字、字母和特殊符号以及最后的规则(最难的):不是包含三个连续的字母或三个连续的数字。
为了说明最后一条规则:Mz2a%yc98B
将不被接受,因为它包含 3 个连续的字母:aBc
前两条规则我做得很好,但我不知道我能为最后一条规则做些什么。我认为这很复杂。有些人告诉我使用正则表达式不可能做到这一点,但实际上它必须是可能的,否则这很疯狂不?
非常感谢!
到目前为止我的代码:
import re
pattern = re.compile(r"")
while True:
password = input("Enter your password")
if re.match(r"(?=.*[a-z])(?=.*[A-Z])(?=(.*[!%@$#&^*()\-__+.]){1,})(?=.*[0-9]).{8,}", password):
result = pattern.match(password)
print("Your password is strong enough")
else:
print("Your password is not strong enough")
而且在我给出的示例密码中,是的,它们是 aBc,B 是最后一个字符。 这只是一个例子。当我指的是连续的时,我指的是字母表中的连续。例如,如果使用甚至散布在密码中的 efg 字母,它必须检测到它。 谢谢
这里是你的问题集的第三个标准的解决方案。
import string
from more_itertools import windowed
alphabet = string.ascii_lowercase
numbers = string.digits
passwords = ["Mz2a%yc98B", "a1b2g3D!", "Tr0ub4dor?"]
def find_triplets(charset: set, target: str) -> bool:
if len(charset) < 3:
return False
else:
chars = "".join(sorted(charset))
triplets = ["".join(tpl) for tpl in windowed(chars, 3)]
return any(triplet in target for triplet in triplets)
for pwd in passwords:
# we use sets to get rid of duplicatess
alpha = set()
nums = set()
for char in pwd:
if char.isalpha():
alpha.add(char.lower())
elif char.isdigit():
nums.add(char)
else:
pass # we don't care about symbols here
if find_triplets(alpha, alphabet) or find_triplets(nums, numbers):
print(f"Your password {pwd} contains 3 consecutive letters or numbers")
else:
print(f"Your password {pwd} is good enough, I guess")
在设置代码之后,我们首先定义一个函数,在输入 charset
被排序并变成字符串后,生成 3 个字符的字符串 (triplets
)。这使用 windowed()
function from the very helpful 3rd party more_itertools
模块。如果函数 returns True
找到与 target
字符串中的连续序列匹配的任何三元组,则函数 False
如果没有。够简单了。
接下来,我们遍历我们的密码列表(您在代码中使用了 input()
,这很好)。首先,我们逐个字符地遍历密码字符串,并将它们添加到适当的集合中(在字母字符的情况下为小写)。然后我们调用我们的 find_triplets()
函数来测试字母或数字的连续运行,并相应地打印一条消息。
您显然想要更改其中的一些内容以适应您的任务,但我会把它留给您。
还有另一种使用 re.search()
的方法,但我认为 any(triplet in target for triplet in triplets)
更加 Pythonic。
你问用正则表达式可能吗?当然!漂亮吗?那是在旁观者的眼中。
您需要一个如下所示的正则表达式(设置了 case-indifferent 标志):
^(?=.*\d)(?=.*[a-z])(?=.*[<special symbols here>])(?!<no 3 digits that are consecutive>)(?!<no three letters that are consecutive>).{8}
让我们看看负面前瞻
(?!<no 3 digits that are consecutive>)
我们可以这样写。
(?!(?:(?=.*0)(?=.*1)(?=.*2))|(?:(?=.*1)(?=.*2)(?=.*3))|(?:(?=.*2)(?=.*3)(?=.*4))|(?:(?=.*3)(?=.*4)(?=.*5))|(?:(?=.*4)(?=.*5)(?=.*6))|(?:(?=.*5)(?=.*6)(?=.*7))|(?:(?=.*6)(?=.*7)(?=.*8))|(?:(?=.*7)(?=.*9)(?=.*9)))
表达式可以写成 verbose 模式(re.X
或 re.VERBOSE
)使其成为 self-documenting.
(?! # begin negative lookahead
(?: # begin non-capture group
(?=.*0) # match > 0 characters followed by 0 (positive lookahead)
(?=.*1) # match > 0 characters followed by 1
(?=.*2) # match > 0 characters followed by 2
) # end non-capture group
| # or
... similar for (?:(?=.*1)(?=.*2)(?=.*3))
...
) # end negative lookahead
构建
(?!<no three letters that are consecutive>)
与 x
、y
和 z
相似(包含 23 个元素的交替,a
、b
和 c
).