2011-01-31 120 views
3

我有一個包含故事數量的大文本文件(大約10 GB)。每個故事從標記$$開始。以下是該文件的示例:如何在不截斷記錄的情況下將大文本文件分割成大小均勻的塊?

$$ 
AA This is story 1 
BB 345 

$$ 

AA This is story 2 
BB 456 

我想將此文件拆分爲大小約爲250 MB的碎片。但是沒有一個故事應該被分成兩個不同的文件。

任何人都可以幫我用這個Unix或Perl代碼嗎?

回答

1

csplit是你想要的。它與split相同,但是基於一個模式。

在C其它++(未測試):

#include <boost/shared_ptr.hpp> 
#include <sstream> 
#include <iostream> 
#include <fstream> 
#include <string> 

void new_output_file(boost::shared_ptr<std::ofstream> &out, const char *prefix) 
{ 
    static int i = 0; 
    std::ostringstream filename; 
    filename << prefix << "_" << i++; 
    out.reset(new std::ofstream(filename)); 
} 

int main(int argc, char **argv) 
{ 
    std::ifstream in(argv[1]); 
    int i = 0; 
    long size = 0; 
    const long max_size = 200 * 1024 * 1024; 
    std::string line; 
    boost::shared_ptr<std::ofstream> out(NULL); 
    new_output_file(out, argv[2]); 
    while(in.good()) 
    { 
     std::getline(in,line); 
     size += line.length() + 1 /* line termination char */; 
     if(size >= max_size && line.length() && line[0] == '$' && line[1] == '$') 
     { 
      new_output_file(out, argv[2]); 
      size = line.length() + 1; 
     } 
     out << line << std::endl; 
    } 
    return 0; 
} 
+1

似乎並不符合這個問題。 – ysth 2011-01-31 16:52:44

+0

當然可以。你可以提供一個正則表達式作爲你的分裂標準。如果提問者將其設置爲/ \ $ \ $ /,那麼`csplit`應該做他們想要的。 – CanSpice 2011-01-31 18:02:26

+0

@CanSplice:但是我們的目標不是在正則表達式上分割,而是分割大約每個250Mb,而不會破壞\ $ \ $ \ n分離的塊。 csplit不會那樣做。 – ysth 2011-01-31 18:52:55

5
use strict; 
use warnings; 
use autodie; 

$/ = "\$\$\n"; 
my $targetsize = 250*1024*1024; 
my $fileprefix = 'chunk'; 
my $outfile = 0; 
my $outfh; 
my $outsize = 0; 
while (my $story = <>) { 
    chomp($story); 
    next unless $story; # disregard initial empty chunk 
    $story = "$/$story"; 

    # no file open yet, or this story takes us farther from the target size 
    if (! $outfile || abs($outsize - $targetsize) < abs($outsize + length($story) - $targetsize)) { 
     ++$outfile; 
     open $outfh, '>', "$fileprefix$outfile"; 
     $outsize = 0; 
    } 

    $outsize += length($story); 
    print $outfh $story; 
} 
1

我已修改的ysth的代碼,發現它的工作。請提出建議,如果您認爲,您可以修改此以使其更好。

use strict; 
use warnings; 

my $targetsize = 50*1024*1024; 
my $fileprefix = 'chunk'; 
my $outfile = 0; 
my $outsize = 0; 
my $outfh; 
my $temp=''; 
while (my $line = <>) { 
    chomp($line); 
    next unless $line; 
    # discard initial empty chunk 
    if($line =~ /^\$\$$/ || $outfile == 0){ 
     $outsize += length($temp); 
     if ($outfile == 0 || ($outsize - $targetsize) > 0) { 
       ++$outfile; 
       if($outfh) {close($outfh);} 
       open $outfh, '>', "$fileprefix$outfile"; 
       $outsize = 0; 
     } 
     $temp=''; 
    } 
    $temp = $temp.$line; 
    print $outfh "$line\n"; 
} 
相關問題