
我有一個巨大的 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 兩次並讀取所有這些位元組兩次。
有沒有辦法一次完成這一切?
我不確定我的 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
我說“這並不能回答我的問題”,因為它仍然需要兩次遍歷文件:一次是找到我正在尋找的內容的偏移量,另一次是修剪文件。
如果我要回到我的自訂程序,我可以實現一個KMP在程式的「唯讀」階段,然後切換到「讀+寫所有內容」。
答案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;
}
所以基本上它會在模式之後開始列印內容,也可以將其直接透過管道傳輸到 bzip2/gzip,就像您在 Debian 上perl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2
需要的那樣。libio-compress-perl