合并具有不同列和行的文件linux

时间:2017-04-18 20:35:01

标签: awk

我有一些我需要加入的文件,我找了一些解决方案,但它们不符合我的需要,我有以下文件

a.csv

  

日期| A | B | C | D
  15-03-2017 | 1 | 3 | 9 | 4

和 b.csv

  

日期| A | C | D | E
  16-03-2017 | 2 | 9 | 3 | 4

我想得到下一个输出:

  

日期| A | B | C | D | E
  15-03-2017 | 1个| 3个| 9个| 4个| 0
  16-03-2017 | 2 | 0 | 9 | 3 | 4

任何见解或建议都表示赞赏!

编辑: 谢谢大家

这些文件示例并不总是相同的 有时它可以有10到50列,1到30行(日期)

4 个答案:

答案 0 :(得分:0)

像这样......

awk 'BEGIN  {FS=OFS="|"} 
     FNR==1 {split($0,h); next} 
            {c++; 
             for(i=1;i<=NF;i++) 
                {a[h[i],c]=$i; 
                 hall[h[i]]}} 
     END    {for(k in hall) printf "%s", k OFS; 
             print "";
             for(i=1;i<=c;i++) 
                {for(k in hall) printf "%s", ((k,i) in a?a[k,i]:0) OFS; 
                 print ""}}' file1 file2

A|B|C|D|E|date |
1|3|9|4|0|15-03-2017|
2|0|9|3|4|16-03-2017|

您可以使用一些额外的代码对列进行重新排序,但也许会出现更好的解决方案......

答案 1 :(得分:0)

使用sed

的稍微简单的解决方案
sed 's/$/|0/;1s/0/E/' a.csv; sed '1d;s/|/|0|/2' b.csv

答案 2 :(得分:0)

我正在将我的答案扩展到脚本中以便于阅读。您可以将脚本与awk -f选项一起使用。从BEGIN语句开始:指定|作为字段分隔符,使用关联数组将索引映射到每个标题标签并打印完整标题。对于每个文件,将标签映射到第1行的索引。然后将标签映射到第2行的数据,并用&#34; 0&#34;替换空数据字段。打印填写的行并清除下一个文件的数组。

BEGIN{
    # field separator
    FS="|"

    # index:label mapping
    map[1]="date "; map[2]="A"; map[3]="B"
    map[4]="C"; map[5]="D"; map[6]="E"

    # print full header
    print "date |A|B|C|D|E"
}

# first line of each file, create index:label mapping
FNR==1{

    for (i=1;i<=NF;i++)
        label[i]=$i
}

# next line of the file, create label:data mapping
FNR==2{
    for (i=1;i<=NF;i++)
        data[label[i]]=$i

    # cycle through index:label mapping and print data
    # for each label or "0" if there is no data
    printf("%s", data["date "])
    for (i=2;i<=6;i++) {
        (data[map[i]]) ? s=data[map[i]] : s=0
        printf("|%s", s)
        }
    print ""  # print empty string for newline

    # delete arrays to start from scratch on the following file
    delete label  
    delete data
}

两个示例文件的结果:

$ awk -f joiner.awk a.csv b.csv 
date |A|B|C|D|E
15-03-2017|1|3|9|4|0
16-03-2017|2|0|9|3|4

答案 3 :(得分:0)

我解决了这个问题

我改变了获取数据的方式

这样的事情:

database 07/05/2017
jdb_A 4345
jdb_CFX 7654
jdb_ZZXD 97865

输出如下:

jdb_20170507.txt:

database 08/05/2017
jdb_A 9876
jdb_CFX 7545
jdb_ZXCFG  2344

jdb_20170508.txt:

x=0
touch jdbaux$x.txt
for jdbfile in $(ls -1t|grep jdb2)
  do
    y=$(($x+1))
    join -a1 -a2 -e0 -o auto --nocheck-order jdbaux$x.txt $jdbfile >jdbaux$y.txt
    rm jdbaux$x.txt
    x=$(($x+1))
done

为jdb_20170508.txt中的这个例子删除了jdb_ZZXD数据库并创建了jdb_ZXCFG数据库

使用此结构我可以使用JOIN命令:

database 07/05/2017 08/05/2017
jdb_A 4345 9876
jdb_CFX 7654 7545
jdb_ZZXD 97865 0
jdb_ZXCFG 0 2344

这是我当月所有档案的递归JOIN质朴选项

-a1 =文件一

-a2 =文件二

-e0 =用0

替换丢失的输入字段

-o auto =输出自动格式

- nocheck-order =不检查输入是否正确排序

输出如下: jdb_sizes201705.txt:

cat jdb_sizes201705.txt |awk '
{ 
  for (i=1; i<=NF; i++)  {
    a[NR,i] = $i
  }
}
NF>p { p = NF }
END {    
    for(j=1; j<=p; j++) {
      str=a[1,j]
        for(i=2; i<=NR; i++){
          str=str" "a[i,j];
        }
        print str
    }
}'

,最后一步是一个枢纽

database jdb_A jdb_CFX jdb_ZZXD jdb_ZXCFG
07/05/2017 4345 7654 97865 0
08/05/2017 9876 7545 0 2344

获得预期的产出

{

  "apps": [
    {

      "index": "index-dev.html",
}
}

我知道这不是最好的解决方案但是有效!

谢谢!