【问题标题】:How to find lines containing a match between two files in perl?如何在perl中查找包含两个文件之间匹配的行?
【发布时间】:2015-04-03 21:38:37
【问题描述】:

我是使用 perl 的新手。我想要做的是比较两个文件。一个是我称之为“临时”的索引文件。我正在尝试使用它来搜索我称为“数组”的主文件。索引文件中只有数字。我的数组中有一些具有这些数字的行。我一直试图找到这两个文件之间的交集,但我的代码不起作用。这就是我一直在尝试做的事情。

#!/usr/bin/perl
print "Enter the input file:";
my $filename=<STDIN>;
open (FILE, "$filename") || die "Cannot open file: $!";
my @array=<FILE>;
close(FILE);
print "Enter the index file:";
my $temp=<STDIN>;
open (TEMP, "$temp") || die "Cannot open file: $!";
my @temp=<TEMP>;
close(TEMP);
my %seen= ();
foreach (@array) {
    $seen{$_}=1;
 }
 my @intersection=grep($seen{$_}, @temp);
 foreach (@intersection) {
    print "$_\n";
 }

如果我不能使用交集,那么我还能做些什么来移动两个文件之间匹配的每一行?

对于那些要求主文件和索引文件的人:

主文件:

 1  CP  TRT 
 ...
 14  C1  MPE 
 15  C2  MPE 
 ...
 20  CA1 MPE 

索引文件

 20
 24
 22
 17
 18
 ...

我想将那些包含索引文件中数字之一的行放入一个新数组中。所以使用这个例子,只有 20 CA1 MPE 将被放置到一个新阵列中。 我的主文件和索引文件都比我展示的要长,但希望这能让您了解我正在尝试做什么。

【问题讨论】:

  • 从索引文件和主文件中给出一个示例行。
  • 发布您输入的两个文件的数据和预期的输出。
  • 我用请求的信息更新了主帖

标签: perl


【解决方案1】:

我假设是这样的?

use strict;
use warnings;
use Data::Dumper;

# creating arrays instead of reading from file just for demo
# based on the assumption that your files are 1 number per line
# and no need for any particular parsing
my @array = qw/1 2 3 20 60 50 4 5 6 7/; 
my @index = qw/10 12 5 3 2/;
my @intersection = ();
my %hash1 = map{$_ => 1} @array;

foreach (@index)
{
    if (defined $hash1{$_})
    {
        push @intersection, $_;
    }
}


print Dumper(\@intersection);

==== 出====

$VAR1 = [
      '5',
      '3',
      '2'
    ];

【讨论】:

    【解决方案2】:

    一些事情:

    • 在您的程序中始终包含use strict;use warnings;。这将捕获很多可能的错误。
    • 在读取输入后总是chomp。 Perl 自动将\n 添加到读取的行尾。 chomp 删除 \n
    • 学习更现代形式的 Perl。
    • 使用助记符变量名。 $temp 没有删减。
    • 使用空格使您的代码更具可读性。

    您从未说明您遇到的错误。我认为这与您的主文件的输入与您的索引文件不匹配这一事实有关。

    我使用哈希创建索引,索引文件可以通过my ($index) = split /\s+/, $line;使用:

    #! /usr/bin/env perl
    #
    use strict;
    use warnings;
    use autodie;
    use feature qw(say);
    
    
    print "Input file name: ";
    my $input_file = <STDIN>;
    chomp $input_file;             # Chomp Input!
    
    print "Index file name: ";
    my $index_file = <STDIN>;
    chomp $index_file;             # Chomp Input!
    
    open my $input_fh, "<", $input_file;
    
    my %hash;
    while ( my $line = <$input_fh> ) {
        chomp $line;
        #
        # Using split to find the item to index on
        #
        my ($index) = split /\s+/, $line;
        $hash{$index} = $line;
    }
    close $input_fh;
    
    open my $index_fh, "<", $index_file;
    
    while ( my $index = <$index_fh> ) {
        chomp $index;
        #
        # Now index can look up lines
        #
        if( exists $hash{$index} ) {
            say qq(Index: $index  Line: "$hash{$index}");
        }
        else {
            say qq(Index "$index" doesn't exist in file.);
        }
    }
    

    【讨论】:

      【解决方案3】:
      #!/usr/bin/perl
      use strict;
      use warnings;
      use autodie;
      
      @ARGV = 'main_file';
      
      open(my $fh_idx, '<', 'index_file');
      chomp(my @idx = <$fh_idx>);
      close($fh_idx);
      
      while (defined(my $r = <>)) {
          print $r if grep { $r =~ /^[ \t]*$_/ } @idx;
      }
      

      您可能希望将那些硬编码的文件名替换为&lt;STDIN&gt;

      仅供参考:while 条件内的 defined 调用可能是“optional”。

      【讨论】:

        猜你喜欢
        • 2015-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-27
        • 1970-01-01
        • 2015-09-20
        • 2021-06-23
        • 2022-01-14
        相关资源
        最近更新 更多