一个sed类似于二进制的实用程序称为bbe

一个sed类似于二进制的实用程序称为bbe

我有一些由程序生成的文件,该程序没有在记录末尾添加换行符。我想在记录之间添加换行符,我可以使用简单的 sed 脚本来完成此操作:

sed -e 's/}{/}\n{/g'

问题在于输入文件的大小为多个 GB,因此 sed 的输入行的长度为多个 GB。 sed 尝试在内存中保存一行,但在这种情况下不起作用。我尝试了该--unbuffered选项,但这似乎使它变慢并且不允许它正确完成。

答案1

您可以使用另一个工具来设置输入记录分隔符。例如

  • Perl

    perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
    

    特殊变量$/是输入记录分隔符。将其设置为}{将行定义为以 结尾}{。这样你就可以实现你想要的,而无需将整个内容读入内存。

  • 莫克或呆呆

    awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file 
    

    这是同样的想法。RS="}{"将记录分隔符设置为}{,然后打印}、换行符{(第一条记录除外)和当前记录。

答案2

Perl 来拯救:

perl -i~ -e ' $/ = \1024;
              while (<>) {
                  print "\n" if $closing and /^{/;
                  undef $closing;
                  s/}{/}\n{/g;
                  print;
                  $closing = 1 if /}$/;
              } ' input1 input2

设置$/\1024将以 1024 字节为单位读取文件。该$closing变量处理一个块以 结尾}而下一个块以 开头的情况{

答案3

你应该做:

{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile

这可能是最有效的解决方案。

这可以{}保护任何可能的跟踪数据。通过另一个tr过程,您可以交换它并在第一个字段的头部添加一个空行{。喜欢...

tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}

所以第一个,使用 don 的示例数据,会:

printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; }           |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}

……第二个也是……

printf '{one}{two}{three}{four}'      |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}

第二个示例没有尾随换行符 - 尽管第一个示例有一个。

答案4

一个sed类似于二进制的实用程序称为bbe

我发现在这种情况下使用类似 sed 的语法是最简单的。

很多更喜欢使用该bbe实用程序(可通过您的 {uni,linu}x 的软件包安装 eq 获得apt-get)。或者这里如果您是 git 人群中的一员,尽管我还没有亲自审查过该特定链接。

1. 支持s/before/after/习语

它是一个“二进制块编辑器”,支持类似 sed 的(以及其他)操作。这包括s/before/after/您需要的超级常见替换习语。请注意,因为从 的角度来看本身没有行bbe,所以命令末尾没有“global g”。

作为快速测试(注意必需的-e):

$ echo hello | bbe -e 's/l/(replaced)/'

产生:

he(replaced)(replaced)o

2.在您的具体转换}{情况下}\n{

因此,如果我们有一个巨大的文件,其中包含一百万个数字,格式为{1}{2}{3}……{1000000}没有回车符,我们可以轻松地交换}{}\n{并且每行一个数字。

这将使用以下bbe命令:

bbe -e 's/}{/}\n{/'

正如在此 zsh 循环中所测试的,我们仅抓取其尾部:

$ for ((num=0; num<1000000; num++)) do; echo -n "{$num}"; done | bbe -e 's/}{/}\n{/' | tail

这会产生这样的结果:

{999990}
{999991}
{999992}
{999993}
{999994}
{999995}
{999996}
{999997}
{999998}
{999999}

(当然没有尾随回车符。)

相关内容