Awk 合并多个文件

Awk 合并多个文件,awk,Awk,我尝试合并几个列数相同的文件(正好10个): index lat lon value 文件的行数不同(即文件中缺少一些索引lat lon) 我想获得一个文件: 索引lat lon值\u文件1值\u文件2值\u文件3值\u文件4值\u文件5值\u文件6值\u文件7值\u文件8值\u文件9值\u文件10 50 80 12 50.25 28.52 35.22 78.89 54.42 65.23 89.56 42.25 12.23 40.15 50 80.5 12.5 80.25 0 12.25 56

我尝试合并几个列数相同的文件(正好10个):

index lat lon value
文件的行数不同(即文件中缺少一些
索引lat lon

我想获得一个文件:

索引lat lon值\u文件1值\u文件2值\u文件3值\u文件4值\u文件5值\u文件6值\u文件7值\u文件8值\u文件9值\u文件10

50 80 12 50.25 28.52 35.22 78.89 54.42 65.23 89.56 42.25 12.23 40.15
50 80.5 12.5 80.25 0 12.25 56.55 85.96 41.23 22.12 24.57 18.26 47.89
问题是“索引lat lon”在我的文件中的顺序不同。以下是我的输入(仅显示2个文件),以便更清楚地了解:

文件1(仅显示几行,但实际文件中有更多行):

指示纬度值

50 80 12 50.25
50 80.5 12.5 80.25 
80 80 12 28.52
80 80.5 12.5 35.89
80 80 12 38.52
80 80.5 12.5 38.25
30 28.5 52.5 12.35
30 27.5 55.5 18.52
50 80 12 28.52
文件2:

指示纬度值

50 80 12 50.25
50 80.5 12.5 80.25 
80 80 12 28.52
80 80.5 12.5 35.89
80 80 12 38.52
80 80.5 12.5 38.25
30 28.5 52.5 12.35
30 27.5 55.5 18.52
50 80 12 28.52
所需输出(仅显示前两行):

表示文件的横向值1文件的横向值2文件的横向值3文件的横向值4文件的纵向值5文件的纵向值7文件的纵向值8文件的纵向值9文件的纵向值10

50 80 12 50.25 28.52 35.22 78.89 54.42 65.23 89.56 42.25 12.23 40.15
50 80.5 12.5 80.25 0 12.25 56.55 85.96 41.23 22.12 24.57 18.26 47.89

如何使用awk实现这一点?

下面是一个使用Perl的可能解决方案:

perl -nle '
    ($k1, $k2, $k3, $v) = split;
    push @{$seen{"$k1 $k2 $k3"}}, $v;
    END { print "$_ @{$seen{$_}}" for sort keys %seen }
' input_*
(对awk的翻译留给读者作为练习。)

算法:

我们迭代所有输入文件(指定为命令行参数,
input.*

-n
选项意味着我们循环所有文件的所有行
-l
启用自动线端处理:引入线的
\n
已剥离;打印行在末尾添加一个
\n

-e…
指定代码

我们
将每一行拆分为空格分隔的字段

我们使用前三个字段(用一个空格作为分隔符)作为散列的键(称为
%seen
)。散列将键(由前三个值组成)映射到值数组。我们处理的每一行在其相应哈希项的末尾添加另一个值(使用
push

最后,我们对
%seen
散列的键进行迭代,然后打印键,后跟一个空格,后跟值列表(也是空格分隔的)。(我们对键进行排序,以便在多次运行此代码时获得确定性输出。)


输出将是对应于每个(索引、lat、lon)元组的值列表(来自所有输入值)。它们将根据命令行上指定的输入文件顺序进行排序(第一个文件中的值将首先显示,以此类推)。如果任何输入文件没有为特定(index、lat、lon)元组指定值,则相应的列表将短一个元素。例如,如果只有文件3为(100,0,0)提供了一个值,那么相应的输出将是来自文件3的
100 0 0 0 0 0 0值\u

如果我理解正确,您希望加入每个文件的最后一个值(#4字段),并将3个第一个值作为查找键

如果是,您可以使用以下脚本:

awk '{
  a[$1 OFS $2 OFS $3]=(a[$1 OFS $2 OFS $3]?a[$1 OFS $2 OFS $3] OFS:"") ($4?$4:"0.0")
}
END{ 
  for(i in a) print i,a[i]
}' file1 file2 file3 ...
脚本使用作为参数给出的每个
文件x
的所有第四个值填充数组
a


读取所有文件后,它将打印所有键和值

实现这一点的方法是创建一个数组,该数组不以数字为索引,而是通过前3列进行索引。最简单的方法是

awk '{key=$1 OFS $2 OFS $3}
     {a[key] = a[key] OFS $4}
     END { for (key in a) print key a[key] }' file1 file2 file3 ...
但是,如果希望
0.0
位于文件没有条目的位置,则必须跟踪哪些文件有条目,哪些文件没有条目。一种方法是:

awk '(FNR==1){f++}
     {key=$1 OFS $2 OFS $3}
     { for(i=b[key]+1; i<f; ++i) a[key] = a[key] OFS "0.0"; b[key]=f }
     { a[key] = a[key] OFS $4 }
     END { for (key in a) {
              for(i=b[key]+1;i<=f; ++i) a[key] = a[key] OFS "0.0";
              print key a[key]
           }
     }' file1 file2 file3 ...
awk'(FNR==1){f++}
{key=$1 OFS$2 OFS$3}

{for(i=b[key]+1、 我不清楚,您能否提供更多详细信息?请阅读您的问题,以准确显示您需要从您提供的示例输入中获得的完整输出,以便我们可以测试潜在解决方案。在我看来,您希望在前三列匹配时合并多个文件的最后一列。但是,如果ex file7没有该特定的键,您希望在那里有一组临时空格,还是忽略它?在这种情况下,我希望“空空格”为0.0。感谢您的帮助!如果缺少值(#4字段)在我的一个文件中,我想要0.0。如何添加它?@user5276228请查看更新的answer@oliv问题说明文件中缺少一些
索引lat lon
。这意味着您的修复程序将无法工作。假设
$1 OFS$2 OFS$3
仅显示在文件5中,或者
$1 OFS$2 OFS$3
仅显示在文件1和文件10。