從大檔案開頭刪除文字的最佳方法

從大檔案開頭刪除文字的最佳方法

我有一個巨大的 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

相關內容