我想使用sed
来获取任意流,并在每个字节后附加一个空字节。
我尝试了很多东西,但遇到了麻烦:
.
似乎是一个子集,即任何字符,而不是任何字节。\0
,但这不起作用。答案 0 :(得分:4)
我建议使用Perl或Python;这是一个(详细的)Perl解决方案:
#!/usr/bin/env perl
use strict;
use warnings;
while (<>)
{
s/./$&\0/gs;
print;
}
对于ASCII文本输入,这为您提供UTF-16LE输出(没有BOM)。鉴于它是Perl,TMTOWTDI,它可以简化为一行;请参阅answer paxdiablo。
鉴于这种显式循环结构,打印BOM的最简单方法是在循环之前添加一个print语句:
printf "%c%c", 0xFF, 0xFE;
给定一个单行,你需要一个BEGIN块:
perl -pe 'BEGIN{printf "%c%c", 0xFF, 0xFE;} s/(.)/\1\0/gs;' "$@"
该剧本中至少有4个,可以说是5个多余的空格。
修改后的问题是:
我想使用sed来获取任意一个UTF-8流并附加一个空字节将其转换为每个字节UTF-16。实现这一目标的神奇之处是什么?
修订后的问题与原文有很大的不同。将UTF-8转换为UTF-16通常是中等复杂的;您必须读取1-4个字节的输入,并生成2或4个字节的输出,担心代理和输入格式错误等。原始问题 - 如何在输入中的每个字符后添加NUL(或零)字节 - 更简单,更简单。 (如果输入是ASCII - 0到127之间的7位字节值 - 那么'之后添加NUL'会给你UTF-16LE。但是只有当UTF-8数据在ASCII子集中时才是这样。)
但是,为了准确翻译,选择的工具应为iconv
:
Usage: iconv [OPTION...] [-f ENCODING] [-t ENCODING] [INPUTFILE...]
or: iconv -l
Converts text from one encoding to another encoding.
Options controlling the input and output format:
-f ENCODING, --from-code=ENCODING
the encoding of the input
-t ENCODING, --to-code=ENCODING
the encoding of the output
Options controlling conversion problems:
-c discard unconvertible characters
--unicode-subst=FORMATSTRING
substitution for unconvertible Unicode characters
--byte-subst=FORMATSTRING substitution for unconvertible bytes
--widechar-subst=FORMATSTRING
substitution for unconvertible wide characters
Options controlling error output:
-s, --silent suppress error messages about conversion problems
Informative output:
-l, --list list the supported encodings
--help display this help and exit
--version output version information and exit
因此,要从UTF-8转换为UTF-16LE:
iconv -f UTF-8 -t UTF-16LE input > output
有趣的是,我没有看到添加BOM到输出的选项,至少在2007年RHEL 5上没有使用iconv
版本1.11(也不是2006年MacOS X上的相同版本 - 不要不要问,我不知道!)。
答案 1 :(得分:2)
如果你有可用的Perl,你可以使用单行:
perl -pe 's/(.)/\1\0/gs'
对每个角色都这样做。如果您希望按原样保留换行符,请在最后留下s
(但听起来您也希望这些换行完成)。
以下成绩单显示了这一点:
pax$ echo hello | perl -pe 's/(.)/\1\0/g' | od -xcb
0000000 0068 0065 006c 006c 006f 000a
h \0 e \0 l \0 l \0 o \0 \n
150 000 145 000 154 000 154 000 157 000 012
0000013
pax$ echo hello | perl -pe 's/(.)/\1\0/gs' | od -xcb
0000000 0068 0065 006c 006c 006f 000a
h \0 e \0 l \0 l \0 o \0 \n \0
150 000 145 000 154 000 154 000 157 000 012 000
0000014