-1

我有两个文件...第一个是包含 ids 的 .txt 文件...

245406
12432
2343576
213543
Ouad1234
evm.1234

第二个文件在第一列中包含文本,在第二列中包含 ids。有什么方法可以比较两个 id,找到匹配项并在第一列中返回相应的文本?

AUX    2398432
AUL    245406

所以当我解析这两个文件时,脚本应该匹配245406并返回相应的 text AUL

这是我到目前为止所拥有的:

open FH_TF_IDS, "<$ARGV[0]" or die $!; 
while (<FH_TF_IDS>) {
    chomp; 
    @fields=split("\t",$_);
    $hash{$fields[1]}=$fields[0];
} 
close FH_TF_IDS;

open IDS, "<$ARGV[1]" or die $!;
@ids=<IDS>; 
close IDS; 

foreach $id (@ids){ 
    $hash_count{$hash{$id}}++;
} 

foreach $family (sort (keys %hash_count)) {
    print "$family\t$hash_count{$family}\n";
} 
4

4 回答 4

1

用户1364517,

我认为您在尝试解决问题方面做得很好。但是,我看到了两个问题。

  1. 添加chomp @ids;afterclose IDS;以删除每个数组元素末尾的 \n。
  2. 更改$hash_count{$hash{$id}}++;$hash_count{$hash{$id}} = $id if $hash{$id};

这些微小的变化将使您的程序能够工作。

这是一个更“hacky”(当然不那么惯用)的解决方案——只是为了好玩:

use strict;
use warnings;

my %hash;

{open my $file, "<$ARGV[0]" or die $!;
$hash{$2} = $1 while <$file> =~ /(.*)\t(.*)/;}

{open my $file, "<$ARGV[1]" or die $!;
map{print "$hash{$_}\t$_\n"}sort{$hash{$a} cmp $hash{$b}}
grep{$hash{$_}}map{s/\n\z//r}<$file>;}

使用块以便在my $file超出范围时关闭文件。

希望这可以帮助!

于 2012-04-30T03:42:16.397 回答
0

尝试这个...

    #!/usr/bin/perl
    use Data::Dumper;

    open a1, "<$ARGV[0]";
    while(<a1>) {
        my @a = split " ", $_;

        open b1, "<$ARGV[1]";
        while(<b1>) {
            my @b = split "\n", $_;
            my @test = (split " ", $b[0]);
            if($test[1] == $a[0]) {
                print $test[0]."\n";
            }
        }
        close b1;
    }

在终端中输入以下命令

    perl test.pl a.txt b.txt
于 2012-04-30T16:07:35.920 回答
0

几个建议:

  • 拿起一本关于Modern Perl的书。Perl 是一门充满蹩脚的古老语言。自 1980 年代首次出现以来,您使用 Perl 编程的方式已经发生了多年的变化。不幸的是,太多人从 Perl 5.0 之前的网站上学习 Perl。
  • 在你的程序中使用use strict;和。use warnings;这将捕获您的大部分编程错误。
  • 不要依赖$_。它是全球性的,可能会导致问题。for (@people) {看起来很整洁,但最好这样做for my $person ( @people )
  • /../split'...'中使用join
  • 使用变量作为文件句柄。它们更容易传递给子程序:

这是你的程序:

我用更现代的风格重写了你的程序,它和你所拥有的差不多。我做了一些错误检查,但除此之外,它可以工作:

use strict;
use warnings;
use feature qw(say);  # Nicer that print.
use autodie;          # Will automatically die on open and close errors

if ( @ARGV < 2 ) {
    die qq(Not enough arguments);
}

my $tf_id_file = shift;   # Use variable names and not `@ARGV` directly
my $id_file    = shift;   # Makes your program easier to understand 

open my $tf_ids_fh, "<", $tf_id_file;

my %hash;                # Not a good name for the variable, but that's what you had.
while ( my $line = <$tf_ids_fh> ) {
    chomp $line;         # Always chomp after a read
    my ( $text, $id ) = split /\s+/, $line;  # Use variable names, not @fields
    if ( not defined $id ) {           # Error checking
        die qq(Missing id field in line $. of tf_ids file);
    }
    $hash{$text} = $id;
}
close $tf_ids_fh;

open my $ids_fh, "<", $id_file;
my @ids = <$ids_fh>;
chomp @ids;
close $ids_fh;

my %totals;
for my $id ( @ids ) {
    if ( not exists $totals{ $hash{$id} } ) {   #Initialize hash before adding to it
        $totals{ $hash{$id} } = 0;
    }
    $totals{ $hash{$id} }++;
}

for my $family ( sort keys %totals ) {
    printf "%10.10s %4d\n", $family, $totals{$family};
}

我使用printf来格式化你的打印输出,它比普通的要好一些print

于 2013-08-23T19:27:59.613 回答
0

我了解您是该语言的初学者。有些东西可以帮助您调试程序。

在脚本的顶部“使用 Data::Dumper;”

一旦你这样做了,你就可以输入像 print Dumper( $hash ) 和 print Dumper( $hash_count ) 这样的语句,这两个语句应该可以让你看到你程序中的错误。

作为旁注,通过 perl -d 运行它也是一种选择,如果您要继续使用该语言,您绝对应该学习。

于 2012-04-29T23:10:05.410 回答