中文字符而不是拉丁字符被写入文件

中文字符而不是拉丁字符被写入文件

当我sed像这样运行并打印到控制台时,一切都很好:

sed '/Q/{
s/Q//g
r /Users/ericbrotto/Desktop/question.txt
}' Commision.txt

但是当我这样做并输出 ta 文件时:

sed '/Q/{
s/Q//g
r /Users/ericbrotto/Desktop/question.txt
}' Commision.txt > newFile

...我的新字符串(在之前的输出中被正确替换的字符串)现在读取为一堆亚洲(我相信普通话)字符。

有任何想法吗?

这是一个后续问题我之前提出的问题

答案1

我之前注意到,如果你采用 ASCII 编码的文本(或者等效地,UTF-8 编码的 ASCII 文本)并将其解码为 UTF-16,你经常会得到“中文字符”(不同的字符取决于你是否将其解码为 UTF- 16BE 或 UTF-16LE)。基于此,我认为您正在处理混合编码。我的猜测是,它Commision.txt被编码为 UTF-16BE 或 UTF-16LE,即question.txt纯 ASCII(或 UTF-8 编码的 ASCII),并且最终newFile会成为两个文件的编码的无效组合。

如果您在两个文件中使用相同的编码,事情应该会更好;可能 UTF-8 效果最好。如果您需要最终输出采用其他编码,那么您可以使用图标对其进行转换 ( iconv -f UTF-8 -t UTF-16BE <newFile >newfile.utf16be.txt)。


实际上,ASCII 字符的 UTF-16 编码与 ASCII 编码相同,但在每个 ASCII 字符之间插入了额外的 NUL 字符,并且在整个字符之前或之后再插入一个 NUL(取决于 UTF-16 编码的字节顺序) 。这意味着当直接在 UTF-8 终端上查看时(即“打印到控制台”),编码为 UTF-8 或 UTF-16 的 ASCII 文本将看起来“正常”。

只要文件内容保持独立,任何编码检测查看环境(例如编辑器)都可能正确检测编码(或者至少选择一个足够接近的编码,考虑到 UTF-8 和许多单字节编码是相同的)在 ASCII 范围内)。

但是你有sed将文件混合在一起。很遗憾,sed不够“智能”,无法意识到它正在使用两种不同的文本编码处理文件。您最终会得到(根据我的猜测)一个主要是 UTF-16 编码的文件(来自) ,中间Commision.txt有一个 UTF-8 编码部分(来自)(或者您放置的任何位置)。如果完全解码为 UTF-8,结果可能无效,但如果完全解码为 UTF-16,结果可能有效(尽管 UTF-8 数据所在的位置有一些意外内容)。question.txtQ


这是一个例子:

Commision.txt是 UTF-16BE 编码的 ASCII(带有 BOM)。

% xxd Commision.txt 
0000000: feff 0046 0069 0072 0073 0074 0020 006c  ...F.i.r.s.t. .l
0000010: 0069 006e 0065 000a 004c 0069 006e 0065  .i.n.e...L.i.n.e
0000020: 0020 0077 0069 0074 0068 0020 0061 0020  . .w.i.t.h. .a. 
0000030: 0075 0063 0020 0027 0071 0027 003a 0020  .u.c. .'.q.'.:. 
0000040: 0028 0051 0029 000a 004c 0061 0073 0074  .(.Q.)...L.a.s.t
0000050: 0020 006c 0069 006e 0065 000a            . .l.i.n.e..

question.txt是 ASCII(或 UTF-8 编码的 ASCII)。

% xxd question.txt
0000000: 5768 6174 2069 7320 7468 6520 6169 722d  What is the air-
0000010: 7370 6565 6420 7665 6c6f 6369 7479 206f  speed velocity o
0000020: 6620 616e 2075 6e6c 6164 656e 2073 7761  f an unladen swa
0000030: 6c6c 6f77 3f0a                           llow?.

我将它们与sed

% sed '/Q/{
s/Q//g
r question.txt
}' Commision.txt >newFile

newFile是一个烂摊子。

sed删除了Q单个字节 ( 51) 而不是其两字节 UTF-16 表示形式 ( 00 51)。
这会破坏文件其余部分的两字节对齐,给出奇数而不是偶数的整个长度,并引入 UTF-16 NULL ( 0000)。

% xxd newFile
0000000: feff 0046 0069 0072 0073 0074 0020 006c  ...F.i.r.s.t. .l
0000010: 0069 006e 0065 000a 004c 0069 006e 0065  .i.n.e...L.i.n.e
0000020: 0020 0077 0069 0074 0068 0020 0061 0020  . .w.i.t.h. .a. 
0000030: 0075 0063 0020 0027 0071 0027 003a 0020  .u.c. .'.q.'.:. 
0000040: 0028 0000 2900 0a57 6861 7420 6973 2074  .(..)..What is t
0000050: 6865 2061 6972 2d73 7065 6564 2076 656c  he air-speed vel
0000060: 6f63 6974 7920 6f66 2061 6e20 756e 6c61  ocity of an unla
0000070: 6465 6e20 7377 616c 6c6f 773f 0a00 4c00  den swallow?..L.
0000080: 6100 7300 7400 2000 6c00 6900 6e00 6500  a.s.t. .l.i.n.e.
0000090: 0a                                       .

尽管一团糟,但在我的 UTF-8 终端中看起来还不错。

% cat newFile
First line
Line with a uc 'q': ()
What is the air-speed velocity of an unladen swallow?
Last line

然而,当我在 Vim 中加载它时,事情显然不对劲(实际上在左括号后面有一个 NUL,但它的存在导致这篇文章被截断)。 Vim 警告“第 2 行出现转换错误”。

First line
Line with a uc 'q': (⤀੗桡琠楳⁴桥⁡楲⵳灥敤⁶敬潣楴礠潦⁡渠畮污摥渠獷慬汯眿਀䰀愀猀琀 氀椀渀攀

如果我删除其中的问号question.txt(再次给出偶数个字节)并重新生成newFile,那么我会“返回”最后一行(尽管它粘在第二行的末尾)并避免来自 Vim 的转换警告。

First line
Line with a uc 'q': (⤀੗桡琠楳⁴桥⁡楲⵳灥敤⁶敬潣楴礠潦⁡渠畮污摥渠獷慬汯眊Last line

相关内容