使用AWK基于多个列合并两个文件

时间:2015-08-14 10:55:33

标签: csv awk

我有两个CSV文件,; (分号) 作为分隔符,我 需要基于三列合并 每个文件使用AWK。关键栏目 不是连续的。想法是得到 文件B中的两列并打印出来 在文件A的所有其他列之后。

文件A(键位于A1,A3和A5中):

A1;A2;A3;A4;A5
K1;D1;K2;D2;K3
K4;D3;K5;D4;K6
K7;D5;K8;D6;K9
K1;D7;K2;D8;K3

文件B(B1,B2,B4中的键):

B1;B2;B3;B4;B5
K1;K2;D9;K3;D0
K4;K5;DA;K6;DB
KA;KB;DC;KC;DD

会产生:

A1;A2;A3;A4;A5;;
K1;D1;K2;D2;K3;D9;D0
K4;D3;K5;D4;K6;DA;DB
K7;D5;K8;D6;K9;;
K1;D7;K2;D8;K3;D9;D0

我在SO中找到了几个例子(例如How to merge two files based on the first three columns using awkHow to merge two files using AWK?)和其他地方,但我无法将它们转换为我的需求,因为它们没有被记录在案以及像我这样的AWK n00b真的能理解它们是如何工作的。

我得到的最近的是:

awk -F \; -v OFS=\; 'FNR==NR{c[$1]=$3 FS $5;next}{ print $0, c[$1]}' B A

但它仍然从输出行1和4中遗漏了一个分号 - 或一列:

A1;A2;A3;A4;A5;
K1;D1;K2;D2;K3;D9;D0
K4;D3;K5;D4;K6;DA;DB
K7;D5;K8;D6;K9;
K1;D7;K2;D8;K3;D9;D0

如何说明我想用于比较的列?显然现在它只使用第一列进行比较。

3 个答案:

答案 0 :(得分:2)

这将在不匹配的行上打印而不会有额外的;。您必须先提供B文件。

 awk 'BEGIN {
          OFS=FS=";"
      } 

      FNR==NR {
          key[$1 FS $2 FS $4]=$3 OFS $5
      } 

      FNR!=NR {
          c=$1 FS $3 FS $5; 
          if(c in key) 
               print $0,key[c]; 
          else 
               print
      }'  fileB fileA

如果您需要额外的分隔符,请将上一个print更改为print $0 OFS OFS

答案 1 :(得分:1)

join -j1 -a1 -t';' <(cut -d';' -f 1,3,5 A | sed -e 's/;//g' | paste -d';' - A | sort ) <(cut -d';' -f 1,2,4 B | sed -e 's/;//g' | paste -d';' - B | sort ) | cut -d';' -f2,3,4,5,6,9,11

#the commands on new lines for readability only
#join command, print all of file A, even if unmatching
join -j1 -a1 -t';'
#input from file A
<(cut -d';' -f 1,3,5 A | sed -e 's/;//g' | paste -d';' - A | sort )
#input from file B
<(cut -d';' -f 1,2,4 B | sed -e 's/;//g' | paste -d';' - B | sort )
#selecting the columns
| cut -d';' -f2,3,4,5,6,9,11

在每种情况下:

1)从文件AB

的所需列创建一个虚拟字段

2)然后使用paste将每个伪文件创建为dummy comparison field; rest of file

3)sort join

的可用性输出

4)根据虚拟字段使用join

5)cut来自匹配join的所需列产生

答案 2 :(得分:0)

不确定我是否正确理解了要求,但这给出了给定输入的预期输出:

audience_id

根据问题中的代码,我从

更改了print语句
awk -F \; -v OFS=\; 'FNR==NR{c[$1]=$3 FS $5;next}{ print $0, $1 in c ? c[$1] : ";"}' B A
A1;A2;A3;A4;A5;;
K1;D1;K2;D2;K3;D9;D0
K4;D3;K5;D4;K6;DA;DB
K7;D5;K8;D6;K9;;
K1;D7;K2;D8;K3;D9;D0

print $0, c[$1]