我有 3 个文件,每个文件都有唯一数量的列,所有列均以制表符分隔,但某些列在 3 个文件之间共享。这是我想用来创建某种“聚合”文件的 3 个文件之间的共享列。
下图显示了文件的示例。基本上我想匹配文件之间的 MAIN1 和 MAIN2 列。三个文件之间的两列都必须匹配。
当两个文件之间的 MAIN1 和 MAIN2 匹配时,我想将 file2 中的列“minor8”添加到 file1 中表格的右侧。随后,我想在 file1 表的右侧添加 file3 中的“minor9”,以应对两个文件之间的 MAIN1 和 MAIN2 匹配的情况。因为“minor8”应该紧邻 file1 的最右列(列名称:“minor3”),所以我希望“minor9”紧邻“minor8”进入新的输出文件。 OUTPUT 文件给出了我理想的最终文件应该是什么样子的想法(尽管此示例 OUTPUT 有一些不一致)。
我曾尝试使用一些 awk 命令一次执行一个文件,但从今天起我只了解了一点 awk。
我尝试过类似的事情:
awk 'NR==FNR{a[$1$3]++;next} $1$3 in a {$1$3==$2$3 FS a[$1$3]; print}' file1 file2 > OUTPUT
但显然没有成功,因为可能缺少很多东西或明显错误。
该行还不会考虑 file3 。
如果有人建议如何使用 file1、file2 和 file3 获取 OUTPUT 文件,那就太好了。我希望能吸取您的建议。如果一步将 3 个文件合并为 1 个输出文件太困难(我当然想不出如何做到这一点),请让我知道如何一次对 1 个文件执行此操作。非常欢迎详细的解释。
多谢!
根据前几条评论,我意识到发布的图像没有那么有用,尽管我确实从一位用户那里得到了一个非常有用的解决方案。
基本上这些是 3 个文件的示例(“选项卡”有点混乱)
文件1:
MAIN1 minor1 MAIN2 minor3
1 bla1 a blabla1
1 bla2 b blabla2
1 bla3 c blabla3
2 bla4 a blabla4
2 bla5 d blabla5
3 bla6 e blabla6
4 bla7 f blabla7
5 bla8 a blabla8
5 bla9 g blabla9
文件2:
minor8 MAIN1 MAIN2
yes1 2 d
yes2 3 e
yes3 4 f
yes4 5 a
yes5 5 g
yes6 1 a
yes7 1 b
yes8 1 c
yes9 2 a
文件3:
MAIN1 MAIN2 minor9
5 a sure1
5 g sure2
1 a sure3
1 b sure4
1 c sure5
2 a sure6
2 d sure7
3 e sure8
4 f sure9
所需的输出文件:
MAIN1 minor1 MAIN2 minor3 minor8 minor9
1 bla1 a blabla1 yes6 sure3
1 bla2 b blabla2 yes7 sure4
1 bla3 c blabla3 yes8 sure5
2 bla4 a blabla4 yes9 sure6
2 bla5 d blabla5 yes1 sure7
3 bla6 e blabla6 yes2 sure8
4 bla7 f blabla7 yes3 sure9
5 bla8 a blabla8 yes4 sure1
5 bla9 g blabla9 yes5 sure2
G-Man 的代码能够重新创建此输出文件,所以谢谢 G-Man!
我忘记提及的一件事是,您的代码无法做到(据我所知),如果没有匹配项,它将从 file1 中删除行。
我基本上需要保留文件 1 的这些行,即使文件 2 和 3 的列 MAIN1 和 MAIN2 之间不完全匹配。如果没有匹配项,我只想看到该特定 MAIN1、MAIN2 组合的空列条目...
我希望我的解释方式足够清楚。
无论如何,我非常感谢你们的帮助。希望在不久的将来的某个时候,除了简单地寻求帮助之外,我还能为这个论坛做出贡献......
因此,举例来说(如果文件 2 和 3 有 1 个缺少 MAIN1、MAIN2 组合,则输出可能如下所示):
MAIN1 minor1 MAIN2 minor3 minor8 minor9
1 bla1 a blabla1 yes6 sure3
1 bla2 b blabla2 yes7 sure4
1 bla3 c blabla3 sure5
2 bla4 a blabla4 yes9 sure6
2 bla5 d blabla5 yes1 sure7
3 bla6 e blabla6 yes2 sure8
4 bla7 f blabla7 yes3
5 bla8 a blabla8 yes4 sure1
5 bla9 g blabla9 yes5 sure2
您对如何编辑 G-Man 的代码以使这成为可能有什么建议吗?
答案1
创建以下文件:
merge21
:
开始 { IFS =“\t” OFS =“\t” } NR==FNR { #文件2 关键=$2“,”$3 存在[键] = 1 小8[键] =1 美元 下一个 } {#文件1 键 = $1 "," $3 if (present[key]) 打印 $1, $2, $3, $4,小调8[调] }
merge312
:
开始 { IFS =“\t” OFS =“\t” } NR==FNR { #文件3 关键=$1“,”$2 存在[键] = 1 小9[键] =3 美元 下一个 } {#文件1 + 文件2 键 = $1 "," $3 if (present[key]) 打印 $1, $2, $3, $4,$5,未成年人9[关键] }
它们几乎完全相同;我已将差异加粗。现在输入命令
awk -f merge21 file2 file1 | awk -f merge312 file3 -
这假设您的数据都不包含逗号,但这实际上仅取决于存在一些数据中未出现的字符串。扩展它以支持更多列将是微不足道的;我希望这是显而易见的。这可以可以增强在一次运行中完成所有操作awk
,但这会更复杂一些,并且(IMNSHO)不值得付出努力。
这会产生文件中数据的所谓“内连接”;看INNER 和 OUTER 连接之间的区别在 Stack Overflow 上了解一些定义。如果你想将其更改为“左外连接”,它是在接受的(和淫秽地已投票)
对该问题的回答为(解释为)“第一个表中的所有行,加上其他表中的任何公共行”,将最后一个语句替换merge21
为
if (present[key]) print $1, $2, $3, $4, minor8[key]
else print $1, $2, $3, $4, "-"
同样在merge312
.假设您已经删除了“ 1
c
”行file2
和“ 4
f
”行file4
,您的输出将是
MAIN1 minor1 MAIN2 minor3 minor8 minor9
1 bla1 a blabla1 yes6 sure3
1 bla2 b blabla2 yes7 sure4
1 bla3 c blabla3 - sure5
2 bla4 a blabla4 yes9 sure6
2 bla5 d blabla5 yes1 sure7
3 bla6 e blabla6 yes2 sure8
4 bla7 f blabla7 yes3 -
5 bla8 a blabla8 yes4 sure1
5 bla9 g blabla9 yes5 sure2
并且,显然,您可以删除-
字符与sed
. (当然,如果您的真实数据实际上包含连字符,请选择一些未使用的字符或字符串作为缺失数据的占位符。)