如果两个文件中第一列的内容在 Unix 中匹配,则打印两个文件的列

Printing Columns of two files if content of first column in both file matches in Unix

我有两个文件如下

file1
name|address office
AK|Victoria Street
BK|Admond Street
DK|Business Street

file2
name|address home
AK|Nilofer Villa
ck|Bluewaters
bk|Homingo Apartment

命令或代码行应该比较两个文件的第一列并将列合并为name|address office|address home,并在不匹配的地方替换NA,文件的内容可能会很大。完整输出应如下所示

file3
name|address office|address home
AK|Victoria Street |Nilofer Villa
BK|Admond Street|Homingo Apartment
DK|Business Street|NA
CK|NA|Bluewaters

这是我到目前为止尝试过的方法:

awk -F '|' 'NR==FNR{c[]++;next};c[] > 0' file1 file2

但上面的代码行没有合并,只是根据列名生成不同的输出。那也区分大小写
name|address home AK|Nilofer Villa

请帮助,也检查了几个问题,但没有解决我的目的。

您可以使用 join 命令执行此操作:

$ join -a 1 -a 2 -e NA -o '0,1.2,2.2' -t '|' -i <(sort f1) <(sort f2)
AK|Victoria Street|Nilofer Villa
BK|Admond Street|Homingo Apartment
ck|NA|Bluewaters
DK|Business Street|NA
name|address office|address home

其中:

  • -a 1-a 2 包括来自任一文件的未连接的行。
  • -e-o 一起显示 "NA" 字段。手册页没有提到这一点,但要使用 -e,您 必须 指定 -o。我们只是按以下顺序显示字段:连接列、第一个文件的第二列、第二个文件的第二列。
  • -t 设置分隔符

当然我们还必须在使用 join 之前对文件进行排序(这是必需的),因此我们使用进程替换。如果您的 shell 没有,您可以使用临时文件。

$ cat tst.awk
BEGIN { FS=OFS="|" }
{
    name = (FNR>1 ? toupper() : )
    if (!seen[name]++) {
        names[++numNames] = name
        vals[name,1] = vals[name,2] = "NA"
    }
    vals[name,ARGIND] = 
}
END {
    for (nameNr=1; nameNr<=numNames; nameNr++) {
        name = names[nameNr]
        print name, vals[name,1], vals[name,2]
    }
}

$ awk -f tst.awk file1 file2
name|address office|address home
AK|Victoria Street|Nilofer Villa
BK|Admond Street|Homingo Apartment
DK|Business Street|NA
CK|NA|Bluewaters

以上使用 GNU awk 作为 ARGIND,其他 awk 只需在脚本开头添加 FNR==1{ARGIND++}