Chinaunix

标题: 把一个文件根据其第一列值分割成多个小文件 [打印本页]

作者: fikong2005    时间: 2009-12-17 08:08
标题: 把一个文件根据其第一列值分割成多个小文件
举例如下:
有一个文件内容为:
A||87767
A||98786
A||F9878
B||8789
B||90887
C||8U798

要根据第一列的值,分割成多个小文件
第一列有3种值,因此分割成3个小文件,分别为:
A.TXT:
A||87767
A||98786
A||F9878

B.TXT:
B||8789
B||90887

C.TXT:
C||8U798

同时想问一下,split函数是否无法把||作为分割符?
同时要考虑一下性能问题,因为要转换的文件都是百M级别的。

[ 本帖最后由 fikong2005 于 2009-12-17 09:20 编辑 ]
作者: cobrawgl    时间: 2009-12-17 08:08
#!/usr/bin/perl


use strict;
use warnings;

use IO::File;

my %FH;

while (<DATA>) {
&nbsp;&nbsp;&nbsp;&nbsp;chomp;
&nbsp;&nbsp;&nbsp;&nbsp;my $name = (split //)[0];
&nbsp;&nbsp;&nbsp;&nbsp;$FH{$name}[0] = IO::File->new("> $name.txt") unless exists $FH{$name};
&nbsp;&nbsp;&nbsp;&nbsp;$FH{$name}[0]->print($_ . "\n");
&nbsp;&nbsp;&nbsp;&nbsp;$FH{$name}[1] += 1;
&nbsp;
}

for (keys %FH) {
&nbsp;&nbsp;&nbsp;&nbsp;$FH{$_}[0]->print('HDR' . $FH{$_}[1]) ;
&nbsp;&nbsp;&nbsp;&nbsp;$FH{$_}[0]->close;
}


__DATA__
A||87767
A||98786
A||F9878
B||8789
B||90887
C||8U798


[ 本帖最后由 cobrawgl 于 2009-12-18 13:01 编辑 ]
作者: guap514    时间: 2009-12-17 09:06
split函数是否无法把||作为分割符?

可以  split '\|\|',$str;
作者: yybmsrs    时间: 2009-12-17 09:10
关注下,切割文件没用过
作者: fikong2005    时间: 2009-12-17 09:21
原帖由 guap514 于 2009-12-17 09:06 发表
split函数是否无法把||作为分割符?

可以  split '\|\|',$str;



呵呵,这样真的可以,我之前只是试了:
split /\|\|/,$str;是不可以的。
作者: cobrawgl    时间: 2009-12-17 09:24
#!/usr/bin/perl


use strict;
use warnings;

use IO::File;

my %FH;

$FH{'A'} = IO::File->new('> A.txt') or die;
$FH{'B'} = IO::File->new('> B.txt') or die;
$FH{'C'} = IO::File->new('> C.txt') or die;


while (<DATA>) {
&nbsp;&nbsp;&nbsp;&nbsp;chomp;
&nbsp;&nbsp;&nbsp;&nbsp;$FH{(split //)[0]}->print("$_\n");
}

__DATA__
A||87767
A||98786
A||F9878
B||8789
B||90887
C||8U798

作者: cobrawgl    时间: 2009-12-17 09:31
当然,如果你从外面读的话,把后面的代码修改一下


my $file = 'Your_file_name';
my $fh = IO::File->new($file) or die;

while ($_ = $fh->getline) {
        chomp;
        $FH{(split //)[0]}->print("$_\n");
}
作者: fikong2005    时间: 2009-12-17 09:44
原帖由 cobrawgl 于 2009-12-17 09:24 发表
#!/usr/bin/perl


use strict;
use warnings;

use IO::File;

my %FH;

$FH{'A'} = IO::File->new('> A.txt') or die;
$FH{'B'} = IO::File->new('> B.txt') or die;
$FH{'C'} = IO::File->new(' ...



但是要创建多少个文件句柄是未知的哦,需要根据数据文件有多少个值来调整创建多少个文件句柄。
作者: Cu_fans    时间: 2009-12-17 09:55
写了一个繁琐的。

#!/usr/bin/perl
use warnings;
use strict;

my %hash;
open FHRead, "<", $ARGV[0] or die $!;
while(<FHRead>)
{
        chomp;
        my ($key, $value) = split /\|\|/, $_;
        unless($hash{$key})
        {
                $hash{$key} = [];
        }
        push @{$hash{$key}}, $value;
}

for my $key(keys %hash)
{
        my $result = $key."\.txt";
        open FHWrite, ">", $result or die $!;
        my @arr = @{$hash{$key}};
        for my $member(@arr)
        {
                print FHWrite $key."||$member\n";
        }
        close FHWrite;
}
close FHRead;
作者: fikong2005    时间: 2009-12-17 10:22
原帖由 cobrawgl 于 2009-12-17 10:08 发表
#!/usr/bin/perl



use strict;
use warnings;

use IO::File;

my %FH;

while () {
    my $name = (split //)[0];
    $FH{$name} = IO::File->new("> $name.txt") unless exists $FH{$name}; ...



好的,谢谢!!万分感谢!
不过,还有一个问题是,打开的文件句柄如何关闭呢?

[ 本帖最后由 fikong2005 于 2009-12-17 10:34 编辑 ]
作者: cobrawgl    时间: 2009-12-17 10:30
别忘了付工钱啊


作者: wfnh    时间: 2009-12-17 12:39
IO::File可以这样用的啊?没用过这个模块啊·
作者: xiehc    时间: 2009-12-17 17:01
标题: 回复 #1 fikong2005 的帖子
很强 ,如果是从文件里读入呢,使用open打开吗,楼主说文件上百兆,用open打开 效率会不会很低呢?
作者: chunchengfh    时间: 2009-12-17 18:52
以前用awk解决过一个类似的问题: http://www.linuxsir.org/bbs/thread294499.html

这个问题可以同样的用awk解决如下:
  1. awk -F"|" '{print > $1 }' file.txt
复制代码

Note: 也许需要将'>'改成'>>'
唯一的问题是,只能判断"|", 不能用"||"作为分割符

[ 本帖最后由 chunchengfh 于 2009-12-17 18:55 编辑 ]
作者: atmystate    时间: 2009-12-18 19:10
如果文件行数挺多,未避免检验文件存在的开销,
可以将A之类作为键值,split后面的内容作为内容进行添加,
最后创建文件写文件
作者: flw    时间: 2009-12-18 22:14
原帖由 atmystate 于 2009-12-18 19:10 发表
如果文件行数挺多,未避免检验文件存在的开销,
可以将A之类作为键值,split后面的内容作为内容进行添加,
最后创建文件写文件

错误




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2