如果两个文件中第一列的内容在 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++}
。
我有两个文件如下
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++}
。