我编写了一个简短的 Python 脚本,可以生成六个字符的随机输出。它生成输出,但大多数输出都有无法识别的字符,这些字符以小方框的形式显示,其中有四个字符。有没有什么方法可以去除这些字符?如果没有,我可以让它们可读/可识别吗?谢谢。
脚本
import os
randomString = os.urandom(6)
print(randomString)
区域设置输出
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=en_US.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8
LC_ALL=
答案1
要使用 Python 中的系统 RNG ( /dev/urandom
) 生成随机字母数字字符串,最好使用random.SystemRandom
:
#!/usr/bin/env python3
import random, string
RNG = random.SystemRandom() # Random Number Generator
characters = string.ascii_letters + string.digits # allowed characters
# build a string by choosing a random character from `characters` 6 times:
s = "".join(RNG.choice(characters) for n in range(6))
print(s)
上述方法允许您准确指定允许的字符,并保证输出字符串具有所需的准确长度。
在这个例子中,我决定为string.ascii_letters + string.digits
,结果是abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
。
但是,您也可以使用自己的小脚本(或直接/dev/urandom
使用命令读取 6 个字节head -c 6 /dev/urandom
)并使用以下命令过滤输出以仅显示字母数字字符tr
:
python3 your_script.py | tr -cd '[:alnum:]' ; echo
head -c 6 /dev/urandom | tr -cd '[:alnum:]' ; echo
该tr
命令删除(-d
)所有不属于(-c
= 补充)指定字符集的字符,指定字符'[:alnum:]'
集是所有字母数字字符的特殊简写。
最后echo
只是产生一个换行符。
这样做的缺点是输出字符串的长度未定义,因为您不知道输出中会有多少个有效字符。
但是,如果您不使用 Python 直接读取/dev/urandom
,则可以像下面这样反转管道顺序,以继续过滤随机字节,直到输出达到所需的长度:
tr -cd '[:alnum:]' < /dev/urandom | head -c 6 ; echo
另外,您也可以将任何二进制数据转换为可读字符,只需将其编码为 即可base64
,其字符集为a-z
、A-Z
、0-9
和:/
+
python3 your_script.py | base64
head -c 6 /dev/urandom | base64
请注意,编码字符串的长度base64
始终大于原始数据的长度(以字节为单位)。输出base64
也始终以 结尾==
。
答案2
您需要读取比所需字母和数字数量多 8 倍的字节,然后删除那些未编码字母或数字的字节。
出现带有代码的奇怪方形字符是因为您的语言环境设置为 UTF-8,但您正在读取任意字节,而这些字节/dev/urandom
(当然)不遵守 UTF-8 编码规则。
我不做 Python(但请参阅本答案末尾的编辑,了解可能丑陋的 Python 代码),但使用简单的 shell 脚本很容易实现目标。要生成包含字母和数字的随机密码,您可以使用类似以下内容:
dd if=/dev/urandom bs=512 count=1 2>/dev/null |
tr -cd a-zA-Z0-9 |
cut -c 1-16 ; echo
从 512 个字节中,平均可以提取 124 个字母和数字。(256 个不同字节中有 62 = 2 * 26 + 10 个字母和数字,它们以相同的概率生成。)
您可能需要进行更改a-zA-Z0-9
以删除过于相似的字符。您可能还需要进行更改以更改16
是否需要更长或更短的密码。
例如,生成一个20个字符的密码,消除可能混淆的字符(0O
,1Il
):
$ dd if=/dev/urandom bs=512 count=1 2>/dev/null |
> tr -cd a-km-zA-HJ-NP-Z2-9 |
> cut -c 1-20 ; echo
JaQ2chDci4xVvzZuyGJm
(这是一份抄本,和$
是>
shell 提示符。)
编辑:这是我的 Python 技能的成果:
#! /usr/bin/env python
import os
import re
print(re.sub("[^a-zA-Z0-9]", "", os.urandom(256))[:6])