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

Awk 合并具有不同列和行的文件,awk,Awk,我有一些文件,我需要加入,我已经寻找了一些解决方案,但他们不适合我需要的,我有以下文件 a、 csv 日期| A | B | C | D 2017年3月15日| 1 | 3 | 9 | 4 及 b、 csv 日期| A | C | D | E 2017年3月16日| 2 | 9 | 3 | 4 我想得到下一个输出: 日期| A | B | C | D | E 2017年3月15日| 1 | 3 | 9 | 4 | 0 2017年3月16日| 2 | 0 | 9 | 3 | 4 任何见解或建议都将

我有一些文件,我需要加入,我已经寻找了一些解决方案,但他们不适合我需要的,我有以下文件

a、 csv

日期| A | B | C | D
2017年3月15日| 1 | 3 | 9 | 4

及 b、 csv

日期| A | C | D | E
2017年3月16日| 2 | 9 | 3 | 4

我想得到下一个输出:

日期| A | B | C | D | E
2017年3月15日| 1 | 3 | 9 | 4 | 0
2017年3月16日| 2 | 0 | 9 | 3 | 4

任何见解或建议都将不胜感激

编辑: 谢谢大家

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

类似这样的内容

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|
awk'BEGIN{FS=OFS=“|”}
FNR==1{split($0,h);next}
{c++;
对于(i=1;i类似的东西

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|
awk'BEGIN{FS=OFS=“|”}
FNR==1{split($0,h);next}
{c++;

对于(i=1;i使用
sed的稍微简单的解决方案

sed 's/$/|0/;1s/0/E/' a.csv; sed '1d;s/|/|0|/2' b.csv

使用
sed
的稍微简单的解决方案:

sed 's/$/|0/;1s/0/E/' a.csv; sed '1d;s/|/|0|/2' b.csv

为了可读性,我将答案扩展为一个脚本。您可以使用带有
awk-f
选项的脚本。从
BEGIN
语句开始:指定
作为字段分隔符,使用关联数组将索引映射到每个标题标签,并打印完整的标题。对于每个文件,将标签映射到第1行的索引n将标签映射到第2行的数据,并将空数据字段替换为“0”。打印已填写的行并清除下一个文件的数组

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
选项的脚本。从
BEGIN
语句开始:指定
作为字段分隔符,使用关联数组将索引映射到每个标题标签,并打印完整的标题。对于每个文件,将标签映射到第1行的索引n将标签映射到第2行的数据,并将空数据字段替换为“0”。打印已填写的行并清除下一个文件的数组

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
}
我解决了这个问题

我改变了获取数据的方式

大概是这样的:

today=$(date +%Y%m%d)
echo "DataBase "$(date +%d/%m/%Y)>/jdb"$today".txt
du -s $(ls -l|grep ^d|awk '{print $9})|awk '{print $2" "$1" "}'>>/jdb"$today".txt
输出如下所示:

jdb_20170507.txt:

database 07/05/2017
jdb_A 4345
jdb_CFX 7654
jdb_ZZXD 97865
jdb_20170508.txt:

database 08/05/2017
jdb_A 9876
jdb_CFX 7545
jdb_ZXCFG  2344
为此,jdb_20170508.txt中的示例删除了jdb_ZZXD数据库,并创建了jdb_ZXCFG数据库

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

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
这是本月所有档案的递归联接乡村选项

-a1=文件一

-a2=文件二

-e0=用0替换缺少的输入字段

-o自动=输出自动格式

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

输出如下所示: jdb_sizes201705.txt:

database 07/05/2017 08/05/2017
jdb_A 4345 9876
jdb_CFX 7654 7545
jdb_ZZXD 97865 0
jdb_ZXCFG 0 2344
最后一步是枢轴

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
    }
}'
我知道这不是最好的解决方案,但它很有效

谢谢!

我解决了这个问题

我改变了获取数据的方式

大概是这样的:

today=$(date +%Y%m%d)
echo "DataBase "$(date +%d/%m/%Y)>/jdb"$today".txt
du -s $(ls -l|grep ^d|awk '{print $9})|awk '{print $2" "$1" "}'>>/jdb"$today".txt
输出如下所示:

jdb_20170507.txt:

database 07/05/2017
jdb_A 4345
jdb_CFX 7654
jdb_ZZXD 97865
jdb_20170508.txt:

database 08/05/2017
jdb_A 9876
jdb_CFX 7545
jdb_ZXCFG  2344
为此,jdb_20170508.txt中的示例删除了jdb_ZZXD数据库,并创建了jdb_ZXCFG数据库

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

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
这是本月所有档案的递归联接乡村选项

-a1=文件一

-a2=文件二

-e0=用0替换缺少的输入字段

-o自动=输出自动格式

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

输出如下所示: jdb_sizes201705.txt:

database 07/05/2017 08/05/2017
jdb_A 4345 9876
jdb_CFX 7654 7545
jdb_ZZXD 97865 0
jdb_ZXCFG 0 2344
最后一步是枢轴

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
    }
}'
我知道这不是最好的解决方案,但它很有效


谢谢!

有趣的任务,初始文件可以有多行(两行以上)?这不是
join
的任务。请删除标签。有趣的任务,初始文件可以有多行(两行以上)?这不是
join
的任务。请删除标签。OMG,为我的疏忽道歉(删除答案)谢谢,我为我的疏忽道歉(已删除的答案)。谢谢