如何在 Bash 中没有 "memory issue" 的情况下每第 n 个定界符后插入 \n

How to insert \n after every nth delimiter without "memory issue" in Bash

我有一个以“Ç”作为分隔符的序列大文件。 我们需要在每 40 个“Ç”处拆分成一个新行。

我们已尝试使用 perl/cut 命令,但出现 "out of memory" 错误,因为它是一个巨大的文件并且 read/write一次发生。

所以我想要的是下面的

每出现 40 个定界符就剪切一次,write/flush 到文件中,不保存在内存中,然后对接下来的 40 个定界符再次执行相同操作,依此类推。

这在 Bash 中可以实现吗?

非常感谢任何帮助。

编辑:

这是我们在 PERL 中使用的命令

perl -pe 's{Ç}{++$n % 40 ? $& : "\n"}ge' <file_name>

说数据如下

123ÇasfiÇsadfÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdataÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdata

我想在(比如新行的第 3 个定界符)处剪切并分配给变量或其他内容并将其刷新到文件以便清除内存。

预期输出

123ÇasfiÇsadf
test1Ç123Çasfi
sadfÇtest1Çmock

注意:这是一个巨大的序列文件。 我们能够使用上面的命令实现所需的输出,但是对于更大的文件,它会抛出内存异常,因此我们想要刷新块。

如果 Python 是一个选项,这里是我建议的 C 代码的移植:

# -*- coding: latin1 -*-
import sys

def cvt(fdin, fdout, delim, count):
    curr = count
    while True:
        c = fdin.read(1)
        if c is None or c == '': break
        if c == delim:
            curr -= 1
            if curr == 0:
                curr = count
                c = '\n'
        dummy = fdout.write(c)

cvt(sys.stdin, sys.stdout, 'Ç', 3)

它给出了预期的结果:

echo "123ÇasfiÇsadfÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdataÇtest1Ç123ÇasfiÇsadfÇtest1ÇmockÇdata" | python ess.py
123ÇasfiÇsadf
test1Ç123Çasfi
sadfÇtest1Çmock
dataÇtest1Ç123
asfiÇsadfÇtest1
mockÇdata

有点长,但是告诉Perl把Ç当作记录分隔符而不是\n;然后你可以在阅读时加入 "lines",将它们分批处理,然后分组输出。 (我的 Perl 生锈了;可能有更简单的方法来做到这一点。)

 perl -ne 'BEGIN {$/="Ç"; $c=0; sub d { chomp $out; print "$out\n"; $out=""; $c=0; }}
           $out .= $_; $c++; &d if $c == 3;
           END { &d }' tmp.txt

在脚本的开头,我们将 $/ 从其默认值换行符更改为您的分隔符;现在 "line" 被定义为以 Ç 结尾的字符串。我们初始化一个计数器 $c 来跟踪我们读取了多少行,我们定义了一个子程序来输出在变量 $out 中累积的行,然后重置累加器和计数器。

对于每一行输入,我们首先将该行附加到累加器,递增计数器,然后在计数器的值达到我们的目标组大小时调用我们的输出例程。

最后,我们在输入末尾调用输出例程来刷新累加器中的所有剩余行。