我想知道它是否有可能从短期内写的正则表达式模式中返回一个随机字符。
所以这是我的情况..
我创建了Enum中包含的一些正则表达式模式:
import random
from _operator import invert
from enum import Enum
import re
class RegexExpression(Enum):
LOWERCASE = re.compile('a-z')
UPPERCASE = re.compile('A-Z')
DIGIT = re.compile('\d')
SYMBOLS = re.compile('\W')
我想要将这些作为包含正则表达式所表示的所有字符的字符串返回,基于以下方法:
def create_password(symbol_count, digit_count, lowercase_count, uppercase_count):
pwd = ""
for i in range(1, symbol_count):
pwd.join(random.choice(invert(RegexExpression.SYMBOLS.value)))
for i in range(1, digit_count):
pwd.join(random.choice(invert(RegexExpression.DIGIT.value)))
for i in range(1, lowercase_count):
pwd.join(random.choice(invert(RegexExpression.LOWERCASE.value)))
for i in range(1, uppercase_count):
pwd.join(random.choice(invert(RegexExpression.UPPERCASE.value)))
return pwd
我尝试了几件事,但我发现可能的唯一选择是使用包含长正则表达式模式的枚举,或者如下例所示的字符串:
LOWERCASE = "abcdefghijklmnopqrstuvwxyz"
......等等使用其他变量。
对此方案的任何建议或解决方案?
- 编辑 -
疯狂物理学家为我的问题带来了解决方案 - 非常感谢!这是工作代码:
def generate_password(length):
tmp_length = length
a = random.randint(1, length - 3)
tmp_length -= a
b = random.randint(1, length - a - 2)
tmp_length -= b
c = random.randint(1, length - a - b - 1)
tmp_length -= c
d = tmp_length
pwd = ""
for i in range(0, a):
pwd += random.choice(string.ascii_lowercase)
for i in range(0, b):
pwd += random.choice(string.ascii_uppercase)
for i in range(0, c):
pwd += random.choice(string.digits)
for i in range(0, d):
pwd += random.choice(string.punctuation)
pwd = ''.join(random.sample(pwd, len(pwd)))
return pwd
string
模块具有您想要的所有定义。
RegexExpression.LOWERCASE
使用string.ascii_lowercase
RegexExpression.UPPERCASE
使用string.ascii_uppercase
RegexExpression.DIGIT
使用string.digits
RegexExpression.SYMBOLS
可能最接近string.punctuation
RegEx并不适合这项任务。表达式用于检查角色是否属于某个类。我不知道一个很好的方法来检查字符类的规范而不涉及源代码/实现细节。
手册的秘密模块中有一个配方可能是更好的方法:
https://docs.python.org/3.6/library/secrets.html#recipes-and-best-practices
from secrets import choice
import string
alphabet = string.ascii_letters + string.digits
while True:
password = ''.join(choice(alphabet) for i in range(10))
if (any(c.islower() for c in password)
and any(c.isupper() for c in password)
and sum(c.isdigit() for c in password) >= 3):
break
print(password)
如果您100%坚持使用正则表达式,则需要一个函数将任意字符类转换为字符串。我确信有一种更简单的方法可以做到这一点,但这是一个通用例程:
from operator import methodcaller
from re import finditer
UNICODE_MAX = 0xFFFF
UNICODE = ''.join(map(chr, range(UNICODE_MAX + 1)))
ASCII = UNICODE [:128]
def class_contents(pattern, unicode=True, printable=True):
base = UNICODE if unicode else ASCII
result = map(methodcaller('group'), finditer(pattern, base))
if printable:
result = filter(str.isprintable, result)
return ''.join(result)
现在,您只需将此函数应用于枚举值即可获取可用字符串。
这是一个IDEOne Link来演示结果:https://ideone.com/Rh4xKI。请注意,LOWERCASE
和UPPERCASE
的正则表达式需要用方括号括起来,或者它们是字面上的三字符字符串,而不是字符类。