无论存储在何处或打印在何种显示设备上,所有文本都必须使用一种或另一种编码进行编码。从文本文件中“删除编码”是不可能的。您所能做的就是将文本从其源编码转换为目标编码。一段文本的编码就像能量:你无法创造或摧毁它,你所能做的就是将它从一种形式转换为另一种形式。
打印一段文本时呈现的字素取决于 (1) 文本的编码,(2) 打印文本的程序(具体来说,它是否在将数据传递给显示设备),以及(3)实际负责呈现文本的显示设备的配置和字体支持。在您的情况下,我们谈论的是 (1) 您的文本文件的编码,(2) cat 和 vim,以及 (3) 您的虚拟终端。
cat 实用程序大多不识别文本,并且从不进行任何文本编码转换;它基本上只是将它从输入源接收到的字节复制到它的标准输出。
假设您没有使用非常旧的 vim 版本,它会动态检测文件的编码并在 'fileencoding' 设置中捕获它(注意:对于此检测,它仅尝试在 'fileencodings' 中指定的编码),其内部存储编码使用'encoding'(与我们的目的无关),并在解释键盘输入和向终端打印文本时使用'termencoding'。
根据您的示例输出,我猜测您的文本文件是每个字符一个字节的编码,可能是 latin1,并且您的终端配置为使用 UTF-8 编码。这就是 cat 输出将最后 5 个字节呈现为 REPLACEMENT CHARACTER U+FFFD � 的原因。这 5 个字节代表非 ASCII 字符,因此不是有效的 UTF-8。当您看到 U+FFFD 字形时,您的终端会告诉您您发送了无效的 UTF-8。 (注意:有时终端使用 MEDIUM SHADE U+2592 ▒ 而不是 U+FFFD 来表示无效的 UTF-8 字节,有时您会看到显示设备字体不支持的有效 UTF-8 字符呈现不同的字形;请参阅@ 987654327@.)
但是看起来vim正确识别了文件编码,它的终端编码思想也是正确的。因此,当它将文件内容打印到终端时,它会正确地在源编码字节和相应的 UTF-8 表示之间进行转换。因此,5 个非 ASCII 字符正确显示为正确的字素。
如果我上面的推论是正确的,你不需要改变任何设置; cat、vim 和您的终端都运行正常。
如果您希望能够手动将文件内容打印到终端,而不依赖于 vim,您可以使用iconv 程序执行必要的转换。像这样(假设 latin1 是源编码):
iconv -f latin1 -t UTF-8 file.txt;
通常建议始终尝试使用 UTF-8。我不确定为什么您的 sed 命令不起作用(这取决于您未提供的 sed 命令的详细信息),但您可以通过存储文件的 UTF-8 编码版本来使其工作某处,然后在其上运行 sed 命令:
iconv -f latin1 -t UTF-8 file.txt >file-utf8.txt;
sed '...' file-utf8.txt;
或者,您可以使用管道一次性完成:
iconv -f latin1 -t UTF-8 file.txt| sed '...';