sed:在非常大的文件中,删除 \n 之前的 \r\r

sed:在非常大的文件中,删除 \n 之前的 \r\r

我有一个损坏的磁盘映像文件(约 27 GB),其中所有 \n 字符之前都插入了 \r\r。我想删除所有 \n 之前的这些 \r\r。

我尝试用 awk:

awk '{ sub("\r\r$", ""); print }' mangled.raw > image.raw

但该文件似乎太大:“awk:运行时错误:内存不足”

我也尝试用 sed:

sed 's/\r\r$//g' mangled.raw > image.raw

但这里的输出文件似乎不完整:它只有 20 GB 大小,并且 mangled.raw 的末尾包含许多零字符,而 image.raw 的末尾包含文件的内容。不知何故,sed 似乎在结束之前停止了。

知道如何正确地做到这一点吗?

答案1

Eldering 的评论可能是正确的 - 这取决于损坏是如何发生的。如果它做了等同于s/\n/\r\r\n/那么它是可逆的,但如果它做了s/\r*\n/\r\r\n/那么它就不是。

无论如何,我会使用 perl 来处理这样的事情。与 sed 不同,它从一开始就被设计用于处理非常长的字符串,并且可以包含 NUL 和其他非文本字符。

perl -pe 's/\r\r\n/\n/g' mangled.raw > image.raw

这可能会消耗大量内存,因为它仍然将文件读取为一系列行,并且文件中可能有很大部分没有行,这些\n行将被视为单个“行”。但是,如果您按块读取,则必须小心,不要错过\r\r\n跨越块边界的序列。像这样:

perl -e '
  $/=\65536;
  while(<>) {
    if(/\r\z/) {
      if(length($nextblock=<>)) {
        $_.=$nextblock;
        redo;
      }
    }
    s/\r\r\n/\n/g;
    print;
   }
' mangled.raw > image.raw

编辑:我意识到如果输入的最后一个字节是,上述代码将陷入无限循环\r。它已更新以正确处理这种情况。

编辑2:perl 单行代码包含错误的替换字符。已更新。

相关内容