假设我有两个文件en.csv
和sp.csv
,每个文件都包含两个逗号分隔的记录:
en.csv
:
1,dog,red,car
3,cat,white,boat
sp.csv
:
2,conejo,gris,tren
3,gato,blanco,bote
如果我执行
join -t, -a 1 -a 2 -e MISSING en.csv sp.csv
我得到的输出是:
1,dog,red,car
2,conejo,gris,tren
3,cat,white,boat,gato,blanco,bote
请注意,所有缺少的字段都已折叠。要获得“正确”的完全外连接,我需要指定一种格式;因此
join -t, -a 1 -a 2 -e MISSING -o 0,1.2,1.3,1.4,2.2,2.3,2.4 en.csv sp.csv
产量
1,dog,red,car,MISSING,MISSING,MISSING
2,MISSING,MISSING,MISSING,conejo,gris,tren
3,cat,white,boat,gato,blanco,bote
这种产生完全外连接的方法的一个缺点是需要显式指定最终表的格式,这在编程应用程序中可能不容易做到(连接表的身份仅在运行时才知道)。
最新版本的 GNUjoin
通过支持特殊格式消除了这个缺点auto
。因此,使用join
上面最后一个命令的这样一个版本,可以用更通用的命令代替
join -t, -a 1 -a 2 -e MISSING -o auto en.csv sp.csv
如何使用join
不支持该-o auto
选项的版本实现相同的效果?
背景和细节
我有一个 Unix shell (zsh) 脚本,旨在处理多个 CSV 平面文件,并通过广泛使用 GNUjoin
的 '-o auto' 选项来实现。我需要修改此脚本,以便它可以在可用join
命令不支持该-o auto
选项的环境中工作(例如 BSDjoin
以及旧版本的 GNU的情况join
)。
脚本中此选项的典型用法如下:
_reccut () {
cols="1,$1"
shift
in=$1
shift
if (( $# > 0 )); then
join -t, -a 1 -a 2 -e 'MISSING' -o auto \
<( cut -d, -f $cols $in | sort -t, -k1 ) \
<( _reccut "$@" )
else
cut -d, -f $cols $in | sort -t, -k1
fi
}
我展示这个例子是为了说明-o auto
用显式格式替换是很困难的,因为要包含在这种格式中的字段直到运行时才知道。
上面的函数_reccut
基本上是从文件中提取列,并沿着它们的第一列连接结果表。要查看_reccut
实际效果,想象一下,除了上面提到的文件之外,我们还有文件
de.csv
2,Kaninchen,Grau,Zug
1,Hund,Rot,Auto
然后,例如,要并排显示 的第 3en.csv
列、第 2 列和第 4sp.csv
列以及 de.csv 的第 3 列,可以运行:
% _reccut 3 en.csv 2,4 sp.csv 3 de.csv | cut -d, 2-
red,MISSING,MISSING,Rot
MISSING,conejo,tren,Grau
white,gato,bote,MISSING