免费注册 查看新帖 |

Chinaunix

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

4个文件中寻找相同行 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-07-30 16:20 |只看该作者 |倒序浏览
有4个文件,每个都有15万行左右。每行长度在120个字母左右,要求找出4个文件中都出现过的行,打印出来。
每个文件中不会有重复的行。
下面是我的脚本,发现运行起来非常慢,每100行大约要4~5秒,到10万行时,每100行大约要执行10多秒。
想请位各位高手,有没有快速的方法?非常感谢~~
  1. use warnings;
  2. use strict;

  3. open my $f0, "<", "changes.tcl.core0" or die;
  4. open my $fo, ">", "changes.tcl.same" or die;

  5. `rm changes.tcl.same` if (-e "changes.tcl.same");

  6. my $cnt = 0;
  7. while ( <$f0> ) {
  8.     chomp;
  9.     my @a = `grep '$_' changes.tcl.core* -l`;
  10.     print $fo "$_\n" if @a==4;
  11.     print "cnt=$cnt\n" unless $cnt % 100;
  12.     $cnt = $cnt + 1;
  13. }
  14. print "Done!\n";
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-07-30 16:24 |只看该作者
如果是我,我会遍历四个文件,每行作为hash的key,每行出现一次该key对应的value加1,最后输出value等于4的所有key。

论坛徽章:
0
3 [报告]
发表于 2013-07-30 16:30 |只看该作者
dgtnk 发表于 2013-07-30 16:24
如果是我,我会遍历四个文件,每行作为hash的key,每行出现一次该key对应的value加1,最后输出value等于4的 ...


这样的话,需要把4个文件都同时吃进来,会不会更慢啊?

论坛徽章:
0
4 [报告]
发表于 2013-07-30 16:30 |只看该作者
本帖最后由 Kotokz 于 2013-07-30 16:36 编辑

回复 2# dgtnk

不会有重复行,忽略我把..

论坛徽章:
0
5 [报告]
发表于 2013-07-30 17:22 |只看该作者
回复 3# 午夜凋零


如果有内存占用太大的考虑,可以先对两个文件遍历一遍,然后只留下相同的部分,然后只把相同部分与文件3进行比较还是留下相同的部分,最后比较4

论坛徽章:
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
6 [报告]
发表于 2013-07-30 18:36 |只看该作者
本帖最后由 jason680 于 2013-07-30 18:39 编辑

回复 1# 午夜凋零

Would you like this ...
Note: it works on sorted file only.

# grep . t*
t1:xx1
t1:xxx
t1:yyy
t2:xx2
t2:xxx
t2:yyy
t3:xx3
t3:xxx
t3:yyy
t4:xx4
t4:xxx
t4:yyy

# perl f4.pl t1 t2 t3 t4
xxx
yyy


# cat f4.pl
use strict;
use warnings;

my @aFH;
my @aData;
foreach(@ARGV){
  open(my $sFH, "<", $_) or die "can't open $_\n";
  push @aFH, $sFH;
}
foreach my $sFH (@aFH){
  my $sTmp = readline($sFH);
  push @aData, $sTmp;
}
while(1){
  my $sFHnum = sortdata(@aData);
  if($sFHnum == -1){  # got the same data in @aData
    print $aData[0];      # output it
    $sFHnum = 0;         # and set $sFHnum for first file
  }
  $aData[$sFHnum] = readline($aFH[$sFHnum]);
  if(!defined $aData[$sFHnum]){
    close $_ foreach @aFH;
    exit;
  }
}

sub sortdata{
  my @aData = @_;
  my $sTemp = shift @aData;
  my $sLoc = 0;
  my $sMin = 0;
  my $sEqual = 0;
  foreach(@aData){
    $sLoc++;
    my $sCmp = ($sTemp cmp $_);
    if($sCmp == 0){
      $sEqual++;
      next;
    }
    if($sCmp > 0){
      $sMin = $sLoc;
      $sTemp = $_;
    }
  }
  return( $sEqual == $sLoc ? -1 : $sMin);
  #  -1 for all data are the same
}

   

论坛徽章:
0
7 [报告]
发表于 2013-07-30 19:12 |只看该作者
非常感谢楼上各位大大的解答。

最后小弟还是采用了2楼大哥的方法,发现机器还是挺给力的。

论坛徽章:
0
8 [报告]
发表于 2013-07-30 21:44 |只看该作者
本帖最后由 lhohoz 于 2013-07-30 21:49 编辑
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;

  4. my (@a, @b, @c, @d, @isect);
  5. my (%a, %b, %c, %d, %count);
  6. open(A, "a.txt") or die "can't open : $!";
  7. open(B, "b.txt") or die "can't open : $!";
  8. open(C, "c.txt") or die "can't open : $!";
  9. open(D, "d.txt") or die "can't open : $!";
  10. @a = grep { ! $a{$_}++ } <A>;
  11. @b = grep { ! $b{$_}++ } <B>;
  12. @c = grep { ! $c{$_}++ } <C>;
  13. @d = grep { ! $d{$_}++ } <D>;

  14. foreach my $e (@a, @b, @c, @d) { $count{$e}++ }
  15. foreach my $f (keys %count) {
  16.     if ( $count{$f} == 3 ) {
  17.         push @isect, $f;
  18.     }
  19. }
  20. print "$_\n" for @isect;
复制代码

论坛徽章:
0
9 [报告]
发表于 2013-07-30 22:14 |只看该作者
lhohoz 发表于 2013-07-30 21:44


多谢这位大哥。
个人认为,中间那部分得到4个数组的地方可以去掉,因为前提是不会有重复的行。

论坛徽章:
0
10 [报告]
发表于 2013-07-30 22:20 |只看该作者
回楼上 没有重复的话可以去掉
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP