免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 7353 | 回复: 20
打印 上一主题 下一主题

已解决~用perl将几个txt文件按照每个文件第一列相同名字合并,谢谢 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-09-29 11:24 |只看该作者 |倒序浏览
本帖最后由 baiguihuajl 于 2015-09-30 12:27 编辑

如何用perl,按照每个文件第一列的名字将很多个txt文件合并,并且每一项都保留,存在的就打印出来,不存在的就用0表示
如:将1.txt 2.txt 3.txt 4.txt 四个文件合并:
1.txt:
a        1
b        2
c        2
d        4
e        1
f        3
g        1
s        2
h        1
2.txt:
a        1
c        1
d        2
e        3
f        1
g        2
h        2
i        2
j        1
3.txt:
b        1
c        2
d        1
e        2
f        2
g        2
h        1
4.txt:
a        2
b        1
c        2
d        3
e        4
f        5
g        1
h        3
合并以后变成这样的效果(可以没有顺序输出):
d        4        2        1        3
c        2        1        2        2
i        0        2        0        0
h        1        2        1        3
e        1        3        2        4
f        3        1        2        5
b        2        0        1        1
g        1        2        2        1
j        0        1        0        0
s        2        0        0        0
a        1        1        0        2

论坛徽章:
0
2 [报告]
发表于 2015-09-29 11:26 |只看该作者
本帖最后由 baiguihuajl 于 2015-09-29 11:27 编辑

我的程序是:
  1. for($i=1;$i<=4;$i++){
  2.         open(F1,"$i.txt");
  3.         while(<F1>){
  4.                 chomp;
  5.                 @a=split(/\t/,$_);
  6.                 foreach($a[0]){
  7.                         next if exists $lines{$_};
  8.                         $lines{$_}=1;
  9.                 }
  10.         }
  11.         close(F1);
  12. }

  13. for($i=1;$i<=4;$i++){
  14.         open(F2,"$i.txt");
  15.         while(<F2>){
  16.                 chomp;
  17.                 @b=split(/\t/,$_);
  18.                 foreach($b[0]){
  19.                         if(exists $lines{$b[0]}){
  20.                                 $lines{$b[0]}.="\t".$b[1];
  21.                         }else{
  22.                                 $lines{$_}.="\t"."0";
  23.                         }
  24.                 }
  25.         }
  26.         close(F2);
  27. }


  28. open out,">>out.txt";
  29. foreach (keys %lines){
  30.         print out "$_\t$lines{$_}\n";
  31. }
复制代码
结果是:
a        1        1        2
h        1        1        2        1        3
b        1        2        1        1
c        1        2        1        2        2
s        1        2
d        1        4        2        1        3
f        1        3        1        2        5
a        1        1        1        2
g        1        1        2        2        1
e        1        1        3        2        4
j        1        1
i        1        2

有谁可以帮我改一下,谢谢~~~

论坛徽章:
0
3 [报告]
发表于 2015-09-29 13:52 |只看该作者
回复 1# baiguihuajl

#!/usr/bin/perl
@_ = qw[1.txt 2.txt 3.txt 4.txt];
for my $i ( 0 .. $#_ ) {
    @ARGV = $_[$i];
    while (<>) {
        ( $a, $b ) = split;
        $_{$a} ||= [ (0) x @_ ];
        $_{$a}[$i] = $b;
    }
}

while ( ( $a, $b ) = each %_ ) {
    print join( "\t", $a, @$b ), "\n";
}


   

论坛徽章:
0
4 [报告]
发表于 2015-09-29 13:58 |只看该作者
能帮我改一下代码吗?而且如果我要合并很多的文件的话,应该怎样?谢谢~~~
回复 3# Okelani


   

论坛徽章:
0
5 [报告]
发表于 2015-09-29 14:00 |只看该作者
回复 4# baiguihuajl

@_ = qw[1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt];
   

论坛徽章:
0
6 [报告]
发表于 2015-09-29 14:04 |只看该作者
1000个的话怎么写?==谢谢
回复 5# Okelani


   

论坛徽章:
0
7 [报告]
发表于 2015-09-29 14:27 |只看该作者
回复 6# baiguihuajl
  1.     @_ = map { $_ . '.txt' } 1 .. 1000;
复制代码


my $looo = 1000;
for my $i ( 0 .. $looo - 1 ) {
    @ARGV = ( $i + 1 ) . '.txt';
    ...
    $_{$a} ||= [ (0) x $looo ];
    ....




10000个的话怎么写

my $loooo = 10000;
for my $i ( 0 .. $loooo - 1 ) {
...

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
8 [报告]
发表于 2015-09-29 15:53 |只看该作者
本帖最后由 jason680 于 2015-09-29 20:43 编辑

回复 4# baiguihuajl

>> ...合并以后变成这样的效果(可以没有顺序输出):
>> ...合并很多的文件的话...

$ perl keys.pl *.txt
a        1        1        0        2
b        2        0        1        1
c        2        1        2        2
d        4        2        1        3
e        1        3        2        4
f        3        1        2        5
g        1        2        2        1
h        1        2        1        3
i        0        2        0        0
j        0        1        0        0
s        2        0        0        0

$ cat keys.pl
use strict;
use warnings;

my(%hKey, %hVal);

my @aFile = @ARGV;
while(<>){
  chomp;
  my($sKey, $sVal) = split;
  $hVal{$sKey}{$ARGV} = $sVal;
}

foreach my $sKey(sort keys %hVal){
  my $sVal = "";
  foreach(@aFile){
    $hVal{$sKey}{$_} = 0 if(!exists $hVal{$sKey}{$_});
    $sVal .= "\t$hVal{$sKey}{$_}";
  }
  print "$sKey$sVal\n";
}


   

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
9 [报告]
发表于 2015-09-29 15:55 |只看该作者
本帖最后由 sunzhiguolu 于 2015-09-29 15:57 编辑

回复 1# baiguihuajl
您好, 看了您的代码. 发现您的问题属于代码逻辑问题:
问题代码范围: 19~25 行位置.
for($i=1;$i<=4;$i++){
        open(F2,"$i.txt");
        while(<F2>){
                chomp;
                @b=split(/\t/,$_);
                foreach($b[0]){
                        if(exists $lines{$b[0]}){   #逻辑错误的地方
                                $lines{$b[0]}.="\t".$b[1];
                        }else{
                                $lines{$_}.="\t"."0";
                        }
                }
        }
        close(F2);
}

红色:可以删除部分

  1. #添加的代码:
  2. sub gen_hash_by_file{
  3.     my ($file, %h_file) = shift;
  4.     open (my $fh_file, '<', $file);
  5.     while (<$fh_file>){
  6.         chomp;
  7.         my ($id, $value) = split /\s+/;
  8.         $h_file{$id} = $value;
  9.     }
  10.     close ($fh_file);
  11.     %h_file;
  12. }
复制代码

  1. #修改后的代码: 14~28 行
  2. for (my $i = 1; $i <= 4; $i++ ){
  3.     my %h_file = gen_hash_by_file($i . '.txt');
  4.     foreach my $k (keys %lines){
  5.         if (exists $h_file{$k}){
  6.             $lines{$k} .= "\t" . $h_file{$k};
  7.         }else{
  8.             $lines{$k} .= "\t" . 0;
  9.         }
  10.     }
  11. }
复制代码

论坛徽章:
0
10 [报告]
发表于 2015-09-29 17:05 |只看该作者
  1. #!/usr/bin/perl

  2. use warnings;
  3. use strict;

  4. my %content;

  5. while(my $file_name = <*.txt>)
  6. {
  7.    open FILE_NAME, $file_name;
  8.    while(<FILE_NAME>)
  9.    {
  10.        my @line = split(/\s+/);
  11.        $content{$line[0]}{$file_name} = $line[1];
  12.    }
  13.    print " "x5,$file_name;
  14. }

  15. print "\n";

  16. foreach my $key_out(sort(keys %content))
  17. {
  18.     print "$key_out"," "x5;
  19.     while(my $file_name = <*.txt>)
  20.     {

  21.          if (defined $content{$key_out}{$file_name})
  22.          {
  23.              print $content{$key_out}{$file_name}," "x10;
  24.          }
  25.          else
  26.          {
  27.              print 0, " "x10;
  28.          }
  29.     }
  30.     print "\n";
  31. }
复制代码
回复 1# baiguihuajl


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP