Eri*_*tto 3 shell bash sed shell-script
当我sed像这样运行并打印到控制台时,一切都很好:
sed '/Q/{
s/Q//g
r /Users/ericbrotto/Desktop/question.txt
}' Commision.txt
Run Code Online (Sandbox Code Playgroud)
但是当我这样做并输出 ta 文件时:
sed '/Q/{
s/Q//g
r /Users/ericbrotto/Desktop/question.txt
}' Commision.txt > newFile
Run Code Online (Sandbox Code Playgroud)
...我的新字符串(在之前的输出中被正确替换的字符串)现在读取为一堆亚洲(我相信是普通话)字符。
有任何想法吗?
我之前注意到,如果你把 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 对其进行转换 ( 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(来自question.txt),中间有一个 UTF-8 编码的部分(来自)(或你Q放置的任何地方)。如果完全解码为 UTF-8,结果可能无效,但在完全解码为 UTF-16 时可能有效(尽管 UTF-8 数据所在的位置有一些意想不到的内容)。
下面是一个例子:
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..
Run Code Online (Sandbox Code Playgroud)
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?.
Run Code Online (Sandbox Code Playgroud)
我将它们与sed结合起来。
% sed '/Q/{
s/Q//g
r question.txt
}' Commision.txt >newFile
Run Code Online (Sandbox Code Playgroud)
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 .
Run Code Online (Sandbox Code Playgroud)
尽管一团糟,但在我的 UTF-8 终端中看起来还不错。
% cat newFile
First line
Line with a uc 'q': ()
What is the air-speed velocity of an unladen swallow?
Last line
Run Code Online (Sandbox Code Playgroud)
当我在 Vim 中加载它时,事情显然不对劲(实际上在左括号后面有一个 NUL,但它的存在导致这篇文章被截断)。Vim 警告“第 2 行出现转换错误”。
First line
Line with a uc 'q': (??????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
如果我删除问号 from question.txt(再次给出偶数个字节)并重新生成newFile,那么我会“返回”最后一行(尽管它被卡在第二行的末尾)并避免来自 Vim 的转换警告。
First line
Line with a uc 'q': (????????????????????????????Last line
Run Code Online (Sandbox Code Playgroud)