Awk 合并文件在空字段中打印0

Awk 合并文件在空字段中打印0,awk,Awk,我有5个tab delim文件 文件0基本上是一个键 A C F AA BC CC D KKK S 文件1 文件2 文件3 文件4 我想根据第1列合并所有文件,并在缺少的字段中打印0 A 2 2 2 1 C 3 3 2 3 F 5 7 5 5 AA 5 0 0 0 BC 4 0 0 0 CC 0 0 4 4 D 7 10 7 7 KKK 0 0 0 10 S 0 0 0 0 列必须保持输入文件0、文件1、文件2、文件3、文件4的顺序,而不是awk,但这种在公共字段上连接文件的

我有5个tab delim文件 文件0基本上是一个键

A 
C 
F 
AA 
BC 
CC 
D 
KKK 
S
文件1

文件2

文件3

文件4

我想根据第1列合并所有文件,并在缺少的字段中打印0

A 2 2 2 1
C 3 3 2 3
F 5 7 5 5
AA 5 0 0 0
BC 4 0 0 0
CC 0 0 4 4
D 7 10 7 7
KKK 0 0 0 10
S 0 0 0 0

列必须保持输入文件0、文件1、文件2、文件3、文件4的顺序,而不是awk,但这种在公共字段上连接文件的方式正是其目的。一次只处理两个文件有点复杂;您必须将每个文件的结果作为第一个文件导入下一个文件

$ join -o 0,2.2 -e0 -a1 <(sort file0) <(sort file1) \
  | join -o 0,1.2,2.2 -e0 -a1 - <(sort file2) \
  | join -o 0,1.2,1.3,2.2 -e0 -a1 - <(sort file3) \
  | join -o 0,1.2,1.3,1.4,2.2 -e0 -a1 - <(sort file4) \
  | tr ' ' '\t'
A       2       2       2       1
AA      5       0       0       0
BC      4       0       0       0
C       3       3       2       3
CC      0       0       4       4
D       7       10      7       7
F       5       7       5       5
KKK     0       0       0       10
S       0       0       0       0

$join-o0,2.2-e0-a1不是awk,但这种在公共字段上连接文件的方式正是它的用途。一次只处理两个文件有点复杂;您必须将每个文件的结果作为第一个文件导入下一个文件

$ join -o 0,2.2 -e0 -a1 <(sort file0) <(sort file1) \
  | join -o 0,1.2,2.2 -e0 -a1 - <(sort file2) \
  | join -o 0,1.2,1.3,2.2 -e0 -a1 - <(sort file3) \
  | join -o 0,1.2,1.3,1.4,2.2 -e0 -a1 - <(sort file4) \
  | tr ' ' '\t'
A       2       2       2       1
AA      5       0       0       0
BC      4       0       0       0
C       3       3       2       3
CC      0       0       4       4
D       7       10      7       7
F       5       7       5       5
KKK     0       0       0       10
S       0       0       0       0

$join-o0,2.2-e0-a1
awk
解决方案

awk '
    FNR==1{f++}
    {
        a[f""$1]=$2
        b[$1]++
    }
    END{
        for(i in b){
            printf i" "
            for(j=1;j<=f;j++){
                tmp=j""i
                if(tmp in a){
                    printf a[tmp]" "
                }else{
                    printf 0" "
                }
            }
            print ""
        }
    }
' file*
首先,我将每个文件号的每个值和键值存储在变量a中 然后将所有uniqe密钥存储在变量b中

END
块中,检查键是否存在,是否存在,是否打印它,打印0


我们可以删除
file0
,如果删除它,
awk
显示仅存在于file1,2,3,4中的密钥,…

awk
解决方案

awk '
    FNR==1{f++}
    {
        a[f""$1]=$2
        b[$1]++
    }
    END{
        for(i in b){
            printf i" "
            for(j=1;j<=f;j++){
                tmp=j""i
                if(tmp in a){
                    printf a[tmp]" "
                }else{
                    printf 0" "
                }
            }
            print ""
        }
    }
' file*
首先,我将每个文件号的每个值和键值存储在变量a中 然后将所有uniqe密钥存储在变量b中

END
块中,检查键是否存在,是否存在,是否打印它,打印0


我们可以删除
file0
,如果删除它,
awk
show only exists key in file1,2,3,4,…

我将一直等待,直到您在问题中包含您自己的尝试,但因为您已经有了两个答案

$ cat tst.awk
NR==FNR {
    key2rowNr[$1] = ++numRows
    rowNr2key[numRows] = $1
    next
}
FNR==1 { ++numCols }
{
    rowNr = key2rowNr[$1]
    vals[rowNr,numCols] = $2
}
END {
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        printf "%s", rowNr2key[rowNr]
        for (colNr=1; colNr<=numCols; colNr++) {
            printf "%s%d", OFS, vals[rowNr,colNr]
        }
        print ""
    }
}

$ awk -f tst.awk file0 file1 file2 file3 file4
A 2 2 2 1
C 3 3 2 3
F 5 7 5 5
AA 5 0 0 0
BC 4 0 0 0
CC 0 0 4 4
D 7 10 7 7
KKK 0 0 0 10
S 0 0 0 0
$cat tst.awk
NR==FNR{
key2rowNr[$1]=++numRows
rowNr2key[numRows]=1美元
下一个
}
FNR==1{++numCols}
{
rowNr=key2rowNr[$1]
VAL[rowNr,numCols]=2美元
}
结束{

对于(rowNr=1;rowNr我本来打算等到你在问题中加入了你自己的尝试,但既然你已经有了两个答案

$ cat tst.awk
NR==FNR {
    key2rowNr[$1] = ++numRows
    rowNr2key[numRows] = $1
    next
}
FNR==1 { ++numCols }
{
    rowNr = key2rowNr[$1]
    vals[rowNr,numCols] = $2
}
END {
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        printf "%s", rowNr2key[rowNr]
        for (colNr=1; colNr<=numCols; colNr++) {
            printf "%s%d", OFS, vals[rowNr,colNr]
        }
        print ""
    }
}

$ awk -f tst.awk file0 file1 file2 file3 file4
A 2 2 2 1
C 3 3 2 3
F 5 7 5 5
AA 5 0 0 0
BC 4 0 0 0
CC 0 0 4 4
D 7 10 7 7
KKK 0 0 0 10
S 0 0 0 0
$cat tst.awk
NR==FNR{
key2rowNr[$1]=++numRows
rowNr2key[numRows]=1美元
下一个
}
FNR==1{++numCols}
{
rowNr=key2rowNr[$1]
VAL[rowNr,numCols]=2美元
}
结束{

对于(rowNr=1;rowNr,使用GNU awk,您可以使用
ENDFILE
子句确保所有行中都有足够的元素,例如:

解析.awk

按如下方式运行:

awk -f parse.awk file[0-4]
输出:

aa500
A 2 1
C3 2 3
D 7 10 7 7
公元前400年
抄送0 0 4 4
S 0 0 0 0
kk010
F 5 7 5

注意:此解决方案假定每个文件只有两列(第一列除外)。

使用GNU awk,您可以使用
ENDFILE
子句确保所有行中都有足够的元素,例如:

解析.awk

按如下方式运行:

awk -f parse.awk file[0-4]
输出:

aa500
A 2 1
C3 2 3
D 7 10 7 7
公元前400年
抄送0 0 4 4
S 0 0 0 0
kk010
F 5 7 5

注意:此解决方案假定每个文件只有两列(第一列除外)。

您可以使用coreutils
join
确定缺少的字段并将它们添加到每个文件:

sort file0>file0.sorted
对于文件[1-4]中的文件;执行以下操作
{ 
cat$文件
join-j1-v1文件0.sorted$file.sorted
完成
现在您只需将它们粘贴在一起:

paste file0.sorted \
  <(cut -d' ' -f2 file1.sorted) \
  <(cut -d' ' -f2 file2.sorted) \
  <(cut -d' ' -f2 file3.sorted) \
  <(cut -d' ' -f2 file4.sorted)

您可以使用coreutils
join
来确定缺少的字段,并将它们添加到每个文件中:

sort file0>file0.sorted
对于文件[1-4]中的文件;执行以下操作
{ 
cat$文件
join-j1-v1文件0.sorted$file.sorted
完成
现在您只需将它们粘贴在一起:

paste file0.sorted \
  <(cut -d' ' -f2 file1.sorted) \
  <(cut -d' ' -f2 file2.sorted) \
  <(cut -d' ' -f2 file3.sorted) \
  <(cut -d' ' -f2 file4.sorted)

您需要在您的问题中包含您自己解决问题的尝试,以便我们能够帮助您。请参阅。您需要在您的问题中包含您自己解决问题的尝试,以便我们能够帮助您解决问题。请参阅。在这种特殊情况下,如果您将所有
@Cyrus-Huh替换,您可以保留行的顺序。我很抱歉I’’我很惊讶这是可行的;通常join会抱怨如果输入没有在join列上排序。有趣。有趣。我得到了一些行的错误,并且行数比它应该的大。join:/dev/fd/62:11:未排序:AARS 862 join:/dev/fd/63:11:未排序:AARS 294 join:/dev/fd/63:10:未排序ed:AARS 452 join:/dev/fd/63:114:未排序:ADA 79无法与您提供的示例文件复制。在这种特殊情况下,如果替换所有
@Cyrus Huh,您可以保持行的顺序。我很惊讶这能起作用;如果输入未在join列上排序,join通常会抱怨。有趣。有趣。我明白了正在为某些行设置错误,并且行数超出了应有的范围。join:/dev/fd/62:11:未排序:AARS 862 join:/dev/fd/63:11:未排序:AARS 294 join:/dev/fd/63:10:未排序:AARS 452 join:/dev/fd/63:114:未排序:ADA 79无法与您提供的示例文件一起复制。
s在您的脚本中没有任何作用,您不应该将printf与输入数据一起用作格式化字符串-想象一下
printf$1
printf”%s之间的区别。”,$1
$1
包含像
%s
这样的printf格式字符时。脚本还将在每个输出行中添加尾随空格。几乎可以工作。不确定为什么它会为某些行输出额外的0。谢谢!
“”
s在您的脚本中没有任何作用,您不应该将printf与输入数据一起用作格式化字符串-想象一下
printf$1
printf“%s”之间的区别,$1
$1
包含诸如
%s
之类的printf格式字符时。脚本还将在每个输出行中添加尾随空格。几乎有效。不确定为什么它会为某些行额外输出0。
paste file0.sorted \
  <(cut -d' ' -f2 file1.sorted) \
  <(cut -d' ' -f2 file2.sorted) \
  <(cut -d' ' -f2 file3.sorted) \
  <(cut -d' ' -f2 file4.sorted)