如何从终端输出中删除任何无法识别的字符

如何从终端输出中删除任何无法识别的字符

我编写了一个简短的 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-zA-Z0-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个字符的密码,消除可能混淆的字符(0O1Il):

$ 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])

相关内容