从大文件开头删除文本的最佳方法

Chr*_*ltz 5 text grep dd sed

我有一个巨大的 MySQL 备份文件(来自 mysqldump),其中的表按字母顺序排列。我的恢复失败,我想从备份文件中的下一个表开始。(我已经纠正了这个问题,这实际上并不是一个关于 MySQL 恢复等的问题。)

我想做的是获取我的备份文件,例如backup.sql并修剪文件的开头,直到看到这一行:

-- Table structure for `mytable`
Run Code Online (Sandbox Code Playgroud)

然后之后的所有内容都将最终出现在我的结果文件中,例如backup-secondhalf.sql. 由于文件是 bzip2 压缩的,这有点复杂,但这应该不是什么大问题。

我想我可以这样做:

$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Table structure for table `mytable`' -m 1
Run Code Online (Sandbox Code Playgroud)

这将为我提供文件中我想要修剪的字节偏移。然后:

$ bunzip2 -c backup.sql.bz2 | dd skip=[number from above] | bzip2 -c > backup-secondhalf.sql.bz2
Run Code Online (Sandbox Code Playgroud)

不幸的是,这需要我在文件上运行 Bunzip2 两次并读取所有这些字节两次。

有没有办法一次性完成这一切?

我不确定我的 sed-fu 是否足够强大来执行“删除正则表达式之前的所有行,然后让文件的其余部分通过”表达式。

这是在 Debian Linux 上,所以我有可用的 GNU 工具。

Mar*_*ner 8

bunzip2 -c backup.sql.bz2 | \
  sed -n '/-- Table structure for `mytable`/,$p'
Run Code Online (Sandbox Code Playgroud)

解释:

-n suppress automatic printing of pattern space
Run Code Online (Sandbox Code Playgroud)

地址范围构建:从正则表达式开始

/-- Table structure for  `mytable`/
Run Code Online (Sandbox Code Playgroud)

结束于

$ Match the last line.
Run Code Online (Sandbox Code Playgroud)

命令

p Print the current pattern space.
Run Code Online (Sandbox Code Playgroud)

编辑:根据您转储数据库的方式,您可能会有长的行。GNU sed 可以根据可用内存量来处理它们。


小智 0

我想知道这样的事情是否可以解决问题:

use strict;
use warnings;
use feature 'say';

use IO::Uncompress::Bunzip2 '$Bunzip2Error';

my $file = $ARGV[0] // die "need a file";

my $zh = IO::Uncompress::Bunzip2->new( $file, {
    AutoClose   => 1,
    Transparent => 1,
} ) or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";

my $trigger = undef;
while ( <$zh> ) {
    chomp;
    $trigger = 1 if $_ eq '-- Dumping data for table `experiments`';
    say if $trigger;
}
Run Code Online (Sandbox Code Playgroud)

所以基本上它会在模式之后开始打印内容,也可以将其直接通过管道传输到 bzip2/gzip,就像perl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2 您在 Debian 上需要的那样libio-compress-perl