如果名称多次出现,则从两列中减去并将值相加

时间:2015-07-28 17:35:46

标签: perl awk hash

我正在尝试解析两列并将它们相互减去,然后如果它们对应的名称出现多次,则将它们一起添加。我试图使用 awk 但没有取得多大成功,更多是因为我缺乏使用awk的经验。

下面是一些示例数据和所需的输出以及我到目前为止的脚本。请记住,这是一个通用脚本,而不是我的实际脚本。我使用的列是减法值的第3列和第4列,因此我将从3中减去4。

样本数据

FILE1

red   13
blue  7
green 5
yellow 15
red 14

第一个文件用于生成哈希。如果颜色出现在该列表上,则它满足从第二个文件中进行解析的要求。

FILE2

15 1 10 15 red
10 5 71 90 blue
15 10 15 40 blue
11 10 1 92 green
15 10 7 17 blue

预期产出

  $VAR1 = {
      'red' => 2,
      'blue' => 1,
      'green' => 1,
      'yellow' => 1,
    };  

10 15 red
71 90 blue
15 40 blue
1 92 green
7 17 blue


red 5
blue 54
green 91

如果值存在,我已经拥有调用该脚本的部分脚本,因为它是从另一个文件的列表中提取的。我正在使用类似的示例脚本作为我之前发布的示例,因为我正在将之前的脚本操作到此脚本中。

use strict;

use Data::Dumper;

use warnings;

my %x;

open( FILE1, $ARGV[0] ) or die "Cannot open the file: $!";
while ( my $line = <FILE1> ) {
    my @array = split( " ", $line );
    $x{ $array[0] }++;
}
close FILE1;

print Dumper( \%x );
my %count;
open( FILE2, $ARGV[1] ) or die "Cannot open the file: $!";
while ( my $line = <FILE2> ) {

    my @name = split( " ", $line );
    my $y = $name[4];

    if ( $x{$y} ) {
        print join( "  ", @name[2, 3, 4] ), "\n";
    }
}
close FILE2;

exit;

我不知道实现目标的最简单方法是什么。在这种情况下使用的理想功能是什么?我在考虑在if ( $x{ $y } )语句中使用哈希,但是不知道哈希是否能够实现减去值的目标,然后如果它们是相同的颜色则将它们相加。

2 个答案:

答案 0 :(得分:1)

您似乎很难自己解决这个问题,而且您的问题描述也不精确。请尽量保持Perl代码整洁和缩进;我不应该编辑你的问题,以便我可以阅读它。并为您的标识符使用有意义的名称;调用哈希%x并不能帮助任何人理解你所写的内容

您还应避免在标记中使用HTML。 Stack Overflow使用 markdown 为帖子提供统一且更易读的风格

这个程序解决了我理解你的问题

use strict;
use warnings;
use v5.10.1;
use autodie;

my %wanted;
{
    open my $fh, '<', $ARGV[0];
    while ( <$fh> ) {
        $wanted{$1} = 1 if /(\S+)/;
    }
}

my %counts;
{
    open my $fh, '<', $ARGV[1];
    while ( <$fh> ) {
        my ($n1, $n2, $colour) = (split)[2,3,4];
        $counts{$colour} += $n2 - $n1 if $wanted{$colour};
    }
}

while ( my ($k, $v) = each %counts ) {
    print "$k $v\n";
}

输出

green 91
blue 54
red 5

答案 1 :(得分:0)

要求救援

awk 'FNR == NR {          # collect the keys and count from first file
   ks[$1]++
   next
}

FNR != NR && FNR==1 {     # when switched to second file, print the counts
   print "\t$VAR1={"      # in the format
   for (k in ks) {
     print "\t\t" k "=>" ks[k] ","
   }
   print "\t};\n"
}

{
   print $3,$4,$5         # print the extract from second file
   if ($5 in ks) {        # and compute the accumulated diffs
     ss[$5] += $4 - $3
   }
}

END {                     # finally, print the accumulated diffs
   print "\n"
   for (s in ss) {
     print s, ss[s]
   }
}' file1 file2