还有一种方法可以打印不可打印的字符,即使它们在字符串中作为命令执行,即使在字符串中不可见(透明),并且可以通过使用测量字符串的长度来观察它们的存在len 以及只需将鼠标光标放在字符串的开头并查看/计算您必须点击箭头键多少次才能从开始到结束,因为奇怪的是一些单个字符的长度可以为 3例如,这似乎令人困惑。 (不确定这是否已经在之前的答案中得到证明)
在下面的示例屏幕截图中,我粘贴了一个 135 位的字符串,该字符串具有特定的结构和格式(我必须事先为某些位位置及其总长度手动创建),以便特定的将其解释为 ascii我正在运行的程序,并且在生成的打印字符串中是不可打印的字符,例如 'line break`,它实际上会导致换行(更正:换页,我的意思是新页面,而不是行break) 在打印输出中,打印结果之间有一个额外的完整空白行(见下文):
Example of printing non-printable characters that appear in printed string
Input a string:100100001010000000111000101000101000111011001110001000100001100010111010010101101011100001011000111011001000101001000010011101001000000
HPQGg]+\,vE!:@
>>> len('HPQGg]+\,vE!:@')
17
>>>
在上面的代码摘录中,尝试直接从该站点复制粘贴字符串HPQGg]+\,vE!:@,看看将其粘贴到 Python IDLE 时会发生什么。
提示:您必须点击箭头/光标三次才能跨越从P 到Q 的两个字母,即使它们彼此相邻,因为实际上有一个File Separator ascii 命令在它们之间。
然而,即使我们在将字节数组解码为十六进制时得到相同的起始值,如果我们将该十六进制转换回字节,它们看起来会有所不同(可能缺少编码,不确定),但无论哪种方式,上述输出的程序打印不可打印的字符(我在尝试开发压缩方法/实验时偶然发现了这个)。
>>> bytes(b'HPQGg]+\,vE!:@').hex()
'48501c514767110c5d2b5c2c7645213a40'
>>> bytes.fromhex('48501c514767110c5d2b5c2c7645213a40')
b'HP\x1cQGg\x11\x0c]+\\,vE!:@'
>>> (0x48501c514767110c5d2b5c2c7645213a40 == 0b100100001010000000111000101000101000111011001110001000100001100010111010010101101011100001011000111011001000101001000010011101001000000)
True
>>>
在上面的 135 位字符串中,前 16 组 8 位从大端开始编码每个字符(包括不可打印的),而最后一组 7 位产生@ 符号,如图所示下面:
Technical breakdown of the format of the above 135-bit string
这里的文本是 135 位字符串的细分:
10010000 = H (72)
10100000 = P (80)
00111000 = x1c (28 for File Separator) *
10100010 = Q (81)
10001110 = G(71)
11001110 = g (103)
00100010 = x11 (17 for Device Control 1) *
00011000 = x0c (12 for NP form feed, new page) *
10111010 = ] (93 for right bracket ‘]’
01010110 = + (43 for + sign)
10111000 = \ (92 for backslash)
01011000 = , (44 for comma, ‘,’)
11101100 = v (118)
10001010 = E (69)
01000010 = ! (33 for exclamation)
01110100 = : (58 for colon ‘:’)
1000000 = @ (64 for ‘@’ sign)
因此,在结束时,关于将不可打印为十六进制的子问题的答案,在上面的字节数组中出现了字母x1c,它表示文件分隔符命令,该命令也在提示中注明。如果不包括左侧的前缀b,则字节数组可以被视为字符串,并且该值再次显示在打印字符串中,尽管它是不可见的(尽管可以通过提示和len 观察到它的存在,如上所示命令)。