我想替换一个grep | awk |带有纯perl解决方案的perl命令使其更快更简单地运行。
我希望将input.txt中的每一行与data.txt文件相匹配,并使用匹配的ID名称和数字计算值的平均值。
input.txt包含1列ID号:
FBgn0260798
FBgn0040007
FBgn0046692
我想将每个ID号与相应的ID名称和相关值进行匹配。以下是data.txt的示例,其中第1列是ID号,第2列和第3列是ID name1和ID name2,第3列包含我想要计算平均值的值。
FBgn0260798 CG17665 CG17665 21.4497
FBgn0040007 Gprk1 CG40129 22.4236
FBgn0046692 RpL38 CG18001 1182.88
到目前为止,我使用grep和awk生成一个输出文件,其中包含匹配的ID号和值的相应值,然后使用该输出文件使用以下命令计算计数和平均值:
# First part using grep | awk
exec < input.txt
while read line
do
grep -w $line data.txt | cut -f1,2,3,4 | awk '{print $1,$2,$3,$4} ' >> output.txt
done
# Second part with perl
open my $input, '<', "output_1.txt" or die; ## the output file is from the first part and has the same layout as the data.txt file
my $total = 0;
my $count = 0;
while (<$input>) {
my ($name, $id1, $id2, $value) = split;
$total += $value;
$count += 1;
}
print "The total is $total\n";
print "The count is $count\n";
print "The average is ", $total / $count, "\n";
这两个部分都可以正常工作,但我想通过运行一个脚本来简化它。我一直试图找到一种更快速的方式在perl中运行整个批次但是经过几个小时的阅读后,我完全不知道如何去做。我一直在玩哈希,数组,if和elsif语句而没有成功。如果有人有建议等,那就太好了。
谢谢, 哈丽特
答案 0 :(得分:1)
如果我了解您,您的数据文件包含每行的名称以及该行的值。其他两个ID并不重要。
您将使用名为输入文件的新文件,该文件将包含数据文件中的匹配名称。这些是您想要平均的值。
最快的方法是创建一个由名称键入的哈希值,这些值将是名称中的值 数据文件。因为这是一个哈希,所以您可以快速找到相应的值。这比一遍又一遍地使用相同的数组要快得多。
第一部分将读入data.txt
文件,并将名称和值存储在由名称键入的哈希值中
use strict;
use warnings;
use autodie; # This way, you don't have to check if you can't open the file
use feature qw(say);
use constant {
INPUT_NAME => "input.txt",
DATA_FILE => "data.txt",
};
#
# Read in data.txt and get the values and keys
#
open my $data_fh, "<", DATA_FILE;
my %ids;
while ( my $line = <$data_fh> ) {
chomp $line;
my ($name, $id1, $id2, $value) = split /\s+/, $line;
$ids{$name} = $value;
}
close $data_fh;
现在,您已经拥有此哈希,可以轻松阅读input.txt
文件并在data.txt
文件中找到匹配的名称:
open $input_fh, "<", INPUT_FILE;
my $count = 0;
my $total = 0;
while ( my $name = <$input_fh> ) {
chomp $name;
if ( not defined $ids{$name} ) {
die qq(Cannot find matching id "$name" in data file\n);
}
$total += $ids{$name};
$count += 1;
}
close $input_fh;
say "Average = " $total / $count;
您仔细阅读每个文件一次。我假设每个文件中只有一个 name 的实例。