使用sed散布空字节

时间:2011-07-05 01:49:22

标签: perl sed

我想使用sed来获取任意流,并在每个字节后附加一个空字节。

我尝试了很多东西,但遇到了麻烦:

  1. 匹配任何字节 - .似乎是一个子集,即任何字符,而不是任何字节。
  2. 添加一个空字节 - 我认为它应该是\0,但这不起作用。

2 个答案:

答案 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