我正在尝试匹配并合并两组排序数据,每个文件一组。每个文件包含两列:键字段和关联值。生成的输出应包含三列:键字段、第一个文件中的值(如果有)以及第二个文件中的值(如果有)。我需要包含不匹配的数据行。
第一个文件“约翰”
apple,green
cherry,red
orange,orange
第二个文件“简”
apple,red
banana,yellow
cherry,yellow
kiwi,green
期望的结果
apple,green,red
banana,,yellow
cherry,red,yellow
kiwi,,green
orange,orange,
起初我以为这对我来说是一项微不足道的工作join
LC_ALL=C join -j1 -a1 -a2 -t',' john jane
但结果总是-a1 -a2
将不匹配的值放在第二列中:
apple,green,red
banana,yellow
cherry,red,yellow
kiwi,green
orange,orange
我需要能够看到不匹配的值源自哪个源文件,理想情况是通过将这些值放在结果文件的适当的第二列或第三列中,但我无法找出一种简单的方法来实现这一点,而不需要深入到awk ... getline()
类型构造中。
请问有什么建议吗?
答案1
你要-o auto
:
join -t, -j 1 -a 1 -a 2 -o auto john jane
从man join
:
-o FORMAT
遵守
︙FORMAT
在构造输出线时
如果FORMAT
是关键字'auto
',那么每个文件的第一行决定了每行输出的字段数。
或者更好地解释自GNU Coreutils:加入调用 (点击链接进入join 中的常规选项):
'
-o auto
'如果指定了关键字“
auto
”,则从每个文件的第一行推断输出格式。这与默认输出格式相同,但也确保每行输出相同数量的字段。缺失的字段将被选项替换-e
,多余的字段将被丢弃。
% cat john
apple,green
cherry,red
orange,orange
% cat jane
apple,red
banana,yellow
cherry,yellow
kiwi,green
% join -t, -j 1 -a 1 -a 2 -o auto john jane
apple,green,red
banana,,yellow
cherry,red,yellow
kiwi,,green
orange,orange,
答案2
您可以明确指定输出格式
LC_ALL=C join -o0,1.2,2.2 -j1 -a1 -a2 -t',' john jane
产生
apple,green,red
banana,,yellow
cherry,red,yellow
kiwi,,green
orange,orange,
这里的关键是,连接字段也可以在输出格式中引用0
,这在不可配对行的上下文中非常有用
答案3
这个命令几乎可以做到这一点;如果密钥仅出现在 file1 中,则它会省略尾随逗号。现在没有时间完全调试:
awk -F, 'BEGIN{OFS=","} FNR==NR{val[$1]=$2;next} {val[$1]=val[$1] "," $2}END{for (key in val) {print key, val[key]}}' john jane
输出:
apple,green,red
banana,,yellow
cherry,red,yellow
kiwi,,green
orange,orange
答案4
使用 R 编程语言
将两个数据文件读入R REPL:
> john <- read.csv("/Users/admin/john", header=FALSE, stringsAsFactors=FALSE)
> john
V1 V2
1 apple green
2 cherry red
3 orange orange
>
> jane <- read.csv("/Users/admin/jane", header=FALSE, stringsAsFactors=FALSE)
> jane
V1 V2
1 apple red
2 banana yellow
3 cherry yellow
4 kiwi green
要合并 R REPL 中的数据文件:
> merge(john, jane, by = c("V1"), all=TRUE)
V1 V2.x V2.y
1 apple green red
2 banana <NA> yellow
3 cherry red yellow
4 kiwi <NA> green
5 orange orange <NA>
>
输出到文件(使用write.table
):
> write.table( merge(john, jane, by = c("V1"), all=TRUE), "john_jane.csv", sep=",", quote=F, row.names=F, col.names=F, na="")
生成的文件(“john_jane.csv”):
apple,green,red
banana,,yellow
cherry,red,yellow
kiwi,,green
orange,orange,
从参数中可以看出write.table
,<NA> 值设置为带有 的空字符串na=""
。如需进一步帮助,请在 R REPL 中的提示符处键入命令,前面加一个问号,如?getwd()
、?setwd()
或。?read.csv()
?merge()
[注意:根据 R 安装的年龄,stringsAsFactors=FALSE
在每个函数调用中包含参数可能是多余的]。read.csv()
https://www.r-project.org/
https://cran.r-project.org/index.html