
アルファベット順に並べられたテーブルを含む巨大な MySQL バックアップ ファイル (mysqldump から) があります。復元に失敗し、バックアップ ファイルの次のテーブルで中断したところから再開したいと考えています。(問題は修正しました。これは MySQL の復元などに関する質問ではありません。)
私がやりたいのは、バックアップ ファイルを取得しbackup.sql
、次の行が表示されるまでファイルの先頭を切り取ることです。
-- Table structure for `mytable`
その後のすべては、たとえば という結果ファイルに保存されますbackup-secondhalf.sql
。ファイルが bzip2 で圧縮されているので多少複雑ですが、それほど大きな問題にはなりません。
次のようにできると思います:
$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Table structure for table `mytable`' -m 1
これにより、ファイル内のトリミングしたいバイトオフセットがわかります。まで。 それから:
$ bunzip2 -c backup.sql.bz2 | dd skip=[number from above] | bzip2 -c > backup-secondhalf.sql.bz2
残念ながら、これを行うには、ファイルに対して bunzip2 を 2 回実行し、すべてのバイトを 2 回読み取る必要があります。
これを一度にすべて実行する方法はありますか?
私の sed-fu が「正規表現まですべての行を削除し、ファイルの残りの部分を通過させる」という表現を実行できるほど強力かどうかはわかりません。
これは Debian Linux 上にあるので、GNU ツールが利用できます。
答え1
bunzip2 -c backup.sql.bz2 | \
sed -n '/-- Table structure for `mytable`/,$p'
説明:
-n suppress automatic printing of pattern space
アドレス範囲の構築: 正規表現で開始
/-- Table structure for `mytable`/
終了
$ Match the last line.
指示
p Print the current pattern space.
編集:データベースをどのようにダンプしたかによって、とても長い行。GNU sed は、使用可能なメモリの量までそれらを処理できます。
答え2
注: 実際の回答ではありません
私はこれを解決したいという意欲があったので今、私は先に進み、grep
必要なファイル内のオフセットを見つけるために使用しました。それはうまくいきました。
残念ながら、実行するにdd
は設定が必要ですibs=1
。これは基本的にバッファリングがないことを意味し、パフォーマンスはひどいです。dd が完了するのを待っている間に、バイトをスキップするための独自のカスタムビルド C プログラムを書くのに時間を費やしました。それをやった後、tail
同じことが簡単にできたことがわかりました。
$ bunzip2 -c restore.sql.bz2 | tail -c +[offset] | bzip2 -c > restore-trimmed.sql.bz2
「これは私の質問への答えになっていない」と言うのは、まだファイルを調べるのに 2 回必要だからです。1 回は探しているもののオフセットを見つけるため、もう 1 回はファイルをトリミングするためです。
カスタムプログラムに戻れば、ケムピープログラムの「読み取り専用」フェーズ中に実行し、その後「すべてを読み取り+書き込み」に切り替えます。
答え3
次のようなものが役に立つだろうか:
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;
}
つまり、基本的にはパターンの後に内容を印刷し始めますが、 Debian でperl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2
必要なように、それを bzip2/gzip に直接パイプすることもできますlibio-compress-perl
。