我有一個包含故事數量的大文本文件(大約10 GB)。每個故事從標記$$
開始。以下是該文件的示例:如何在不截斷記錄的情況下將大文本文件分割成大小均勻的塊?
$$
AA This is story 1
BB 345
$$
AA This is story 2
BB 456
我想將此文件拆分爲大小約爲250 MB的碎片。但是沒有一個故事應該被分成兩個不同的文件。
任何人都可以幫我用這個Unix或Perl代碼嗎?
我有一個包含故事數量的大文本文件(大約10 GB)。每個故事從標記$$
開始。以下是該文件的示例:如何在不截斷記錄的情況下將大文本文件分割成大小均勻的塊?
$$
AA This is story 1
BB 345
$$
AA This is story 2
BB 456
我想將此文件拆分爲大小約爲250 MB的碎片。但是沒有一個故事應該被分成兩個不同的文件。
任何人都可以幫我用這個Unix或Perl代碼嗎?
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;
}
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;
}
我已修改的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";
}
似乎並不符合這個問題。 – ysth 2011-01-31 16:52:44
當然可以。你可以提供一個正則表達式作爲你的分裂標準。如果提問者將其設置爲/ \ $ \ $ /,那麼`csplit`應該做他們想要的。 – CanSpice 2011-01-31 18:02:26
@CanSplice:但是我們的目標不是在正則表達式上分割,而是分割大約每個250Mb,而不會破壞\ $ \ $ \ n分離的塊。 csplit不會那樣做。 – ysth 2011-01-31 18:52:55