使用 bytearray.translate() 和 table

Using bytearray.translate() with a table

我正在尝试从字节数组中删除某些字符(具体来说,某些控制字符会弄乱我的格式)

我手动列出了个人翻译并且它有效,但是我可以将其格式化为单个翻译吗? 在字符串变体中,输入可以是字典 table。但是当我尝试这个参数必须是字节数组对象时出现错误。

translation_table_0A = bytes.maketrans(b"\x0A", b"\x00")
translation_table_0B = bytes.maketrans(b"\x0B", b"\x00")
translation_table_0C = bytes.maketrans(b"\x0C", b"\x00")
translation_table_0D = bytes.maketrans(b"\x0D", b"\x00")
translation_table_04 = bytes.maketrans(b"\x04", b"\x00")

test_bytes = bytearray(b"\x75\x66\x73\x62\x0D\x73\x62\x0B\x00\x74\xF1\x74\x73\x62\x61\x76\x00\x0C\x76\x02\x04\x01\x62\x68\x72\x74\x00\x00\x00\x0A\x01\x00")

out_list = test_bytes.translate(translation_table_0A)  # remove \x0A
out_list = out_list.translate(translation_table_0B)  # remove \x0B
out_list = out_list.translate(translation_table_0C)  # remove \x0C
out_list = out_list.translate(translation_table_0D)  # remove \x0D
out_list = out_list.translate(translation_table_04)  # remove \x04

print(f"Output coded: {obj}")
print(f"Output decoded: {obj.decode('mac-roman')}")

我认为它会像这样工作:

translate_dict = {b"\x0A" : b"\x00", b"\x0B" : b"\x00", b"\x0C" : b"\x00", b"\x0D" : b"\x00", b"\x04" : b"\x00", }

out_list = test_bytes.translate(translate_dict)  # remove Control Chars

但事实并非如此。有谁知道如何让它工作?

遗憾的是文档缺少详细信息:
bytes
bytes maketrans()
bytes methods
bytes translate()

通过 maketrans 方法,可以生成 table,但是 'from' 和 'to' 必须是类字节对象,因此元组、列表或字典将不起作用。

注意:对正则表达式解决方案或其他库不感兴趣。专门找这个应用。

如果你想要一个 bytes 翻译 table,你会得到一个 256 字节的字节映射,它由源字节值索引,并且 returns [=映射中的第 37=]n 个字节值。您不必设置 4 个不同的翻译 table 来翻译 4 个字节,您可以这样做:

>>> translation_table = bytes.maketrans(b"\x0A\x0B\x0C\x0D\x04", b"\x00\x00\x00\x00\x00")

这样您就可以将不需要的字节值更改为 \x00,如下所示:

>>> test_bytes=bytearray(b"\x75\x66\x73\x62\x0D\x73\x62\x0B\x00\x74\xF1\x74\x73\x62\x61\x76\x00\x0C\x76\x02\x04\x01\x62\x68\x72\x74\x00\x00\x00\x0A\x01\x00")
>>> test_bytes.translate(translation_table)    
bytearray (b'ufsb\x00sb\x00\x00t\xf1tsbav\x00\x00v\x02\x00\x01bhrt\x00\x00\x00\x00\x01\x00')

看起来与更改了 4 个字节值的 test_bytes 不完全相同,因为字节串中 printable 字符的默认表示是 printable 字符,而不是十六进制逃脱。如果你要求 test_bytes 返回,你可以看到这个:

>>> test_bytes
bytearray (b'ufsb\rsb\x0b\x00t\xf1tsbav\x00\x0cv\x02\x04\x01bhrt\x00\x00\x00\n\x01\x00')

此处 tsbavbhrt 等序列显示为 printable 字符,而不是十六进制转义符。但只是表示方式不同。

如果您正在使用 bytes,则不能使用字典作为翻译 table。在 Python 3 中,字符串是 Unicode,256 字节的映射 table 将不起作用,因为 table 可能需要翻译 1,114,112 个可能的代码点。因此,对于字符串,translate() 使用 dict 代替。虽然高效,但 dict 无法匹配 256 字节的字符映射以提高效率。所以 bytes.maketrans() 生成一个 256 字节的字符映射,但是 str.maketrans() 生成一个 dict,相应的 translate() 方法期望相应类型的转换 table.