合并来自不同文件的数字总和并删除选择的重复行

时间:2018-12-17 19:09:20

标签: bash awk merge

我在这里检查了合并时的其他线程,但是它们似乎主要是关于合并文本,并不是我所需要的,或者至少我无法找到一种将他们的解决方案与我自己的问题联系起来的方法。

问题

我有10多个输入文件,每个输入文件由两列数字组成(将它们视为图形的x,y数据点)。目标:

  • 将这些文件合并为1个文件进行绘图
  • 对于合并中任何重复的x值,请将其各自的y值相加,然后在字段1中打印x,并在字段2中打印添加的y值。

将此示例考虑为3个文件:

y1.dat

 25 16

 27 18

y2.dat

 24 10

 27 9

y3.dat

 24 2

 29 3

根据上述目标,我应该能够将它们合并到一个文件中,并输出:

final.dat

 24 12

 25 16

 27 27

 29 3

尝试

到目前为止,我有以下内容:

#!/bin/bash

loops=3

for i in `seq $loops`; do
if [ $i == 1 ]; then
cp -f y$i.dat final.dat

else
awk 'NR==FNR { arr[NR] = $1; p[NR] = $2; next }  {
       for (n in arr) {
       if ($1 == arr[n]) {
       print $1, p[n] + $2
       n++
       }
      }
   print $1, $2 
}' final.dat y$i.dat >> final.dat

fi
done

输出:

 25 16
 27 18
 24 10
 27 27
 27 9
 24 12
 24 2
 29 3

仔细检查,很明显我有原始x值的副本。

问题是我的脚本需要首先打印所有x值,然后才能将它们添加在一起以进行输出。但是,我不知道如何返回并删除添加相加所需的带有旧x值的行。

如果我盲目使用uniq,我不知道是删除了旧的x值还是新的x值。使用awk'!duplicate [$ 1] ++',删除的行顺序在循环中是相反的,因此它可以在第一个循环中正确删除,但在此之后是错误的。

长期从事此工作,将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:2)

我假设您已经在计算之前将所有文件合并为一个文件。完成后,脚本就很简单了:

awk '{ if ( $1 != "" ) { coord[$1]+=$2 } } END { for ( k in coord ) { print k " " coord[k] } }' input.txt

希望有帮助!

编辑:这是如何工作的?

if ( $1 != "" )  { coord[$1]+=$2 } 

此行将针对您输入中的每一行执行。首先将检查X是否存在值,否则将忽略该行。如果文件有空行,这有助于忽略空行。被执行的代码块: coord [$ 1] + = $ 2 是脚本的核心,并创建一个字典,其中X是每个条目的键,并且同时将找到的Y的每个值相加

END { for ( k in coord ) { print k " " coord[k] } 

awk遍历文件中的所有行之后,将执行此块。它将简单地从字典中获取每个键并打印,然后打印一个空格,最后是找到的所有值的总和,换句话说,就是该特定键的值。

答案 1 :(得分:0)

使用Perl单线版

> cat y1.dat
25 16
27 18
> cat y2.dat
24 10
27 9
> cat y3.dat
24 2
29 3
> perl -lane ' $kv{$F[0]}+=$F[1]; END { print "$_ $kv{$_}" for(sort keys %kv) }' y*dat
24 12
25 16
27 27
29 3
>