我有两个结构相似的文件(制表符分隔,很多很多行,第3列减去第2列= 1),看起来有点像这样:
文件1:
1 170023 170024 A -
1 170024 170025 T -
1 170026 170027 A -
1 170028 170029 G -
1 170029 170030 C -
1 170031 170032 C -
文件2:
1 170023 170024 A
1 170024 170025 T
1 170025 170026 G
1 170026 170027 A
1 170027 170028 G
1 170028 170029 T
1 170029 170030 A
1 170030 170031 G
1 170031 170032 C
我想将文件2中的第4列(仅限字母列)添加到文件1.对于pr
或paste
,这通常很容易,但问题是第1列-3在两个文件中不相同。换句话说,文件具有不同数量的行,文件2总是比文件1更多行(特别是,文件1中找到的第2和第3列中的所有数字也出现在文件2中,但不是反之亦然< / em>的)。我也知道如何在R中执行它但是文件太大而不能在R中轻松处理我将需要为十几个文件执行任务。所以我猜,bash或任何命令行软件都是最有效的解决方案。
我真正想要做的是添加文件2中第4列的字母,当且仅当文件2中的第1-3列完全匹配文件1中的第1-3列时。因此,文件1的第4列和第5列中出现的符号无关紧要。根据上面的文件1和文件2的示例,所需的输出将是:
输出:
1 170023 170024 A - A
1 170024 170025 T - T
1 170026 170027 A - A
1 170028 170029 G - T
1 170029 170030 C - A
1 170031 170032 C - C
如果有人可以帮助我,我会很高兴的。非常感谢你提前!
答案 0 :(得分:1)
我可以考虑使用join
和awk
为此提供一个简单的解决方案。可能不是使用awk
解决问题的最有效方法(可能会因此而被专家抨击:)),但我能够解决这个问题。
<强>解决方案-1: - 强>
您需要做的就是首先使用join
而不指定要加入的任何特定列。它会根据常见的重复列自动连接文件,在本例中为第1列。然后在该输出上,我们可以让awk
播放打印符合您需要的行并格式化所需的列。
join file1 file2 | awk '{ if (($2==$6) && ($3==$7)) printf("%s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $8) }'
将输出生成为
1 170023 170024 A - A
1 170024 170025 T - T
1 170026 170027 A - A
1 170028 170029 G - T
1 170029 170030 C - A
1 170031 170032 C - C
<强>解决方案-2: - 强>
仅使用普通join
join -j 2 file1 file2 -o 1.1,1.2,1.3,1.4,1.5,2.4
也会产生与预期相同的输出。
`join' writes to standard output a line for each pair of input lines that have identical join fields.
引用man
的{{1}}页面内容,如下所示
join
因此,该命令首先通过第2列加入`-j FIELD'
Equivalent to `-1 FIELD -2 FIELD'.
`-o FIELD-LIST'
Otherwise, construct each output line according to the format in
FIELD-LIST. Each element in FIELD-LIST is either the single
character `0' or has the form M.N where the file number, M, is `1'
or `2' and N is a positive field number.
和file1
,然后从看到的输出中打印所需的列,由(file2
,1.1
,{表示{1}},1.2
,1.3
,1.4
),应该被理解为1.5
。2.4
。为了更好地理解,我建议首先看一下没有file
选项的输出,以及我是如何构建输出的。
<强>解决方案-3: - 强>
使用plain'ol column
,我在回答这个问题的时候实际上已经学会了一点。
-o
说明: -
awk
将在awk 'FNR==NR{a[$1 FS $2 FS $3]=$4;next} (($1 FS $2 FS $3) in a) {print $0, a[$1 FS $2 FS $3]}' file2 file1
上处理存储数组FNR==NR{a[$1 FS $2 FS $3]=$4;next}
的条目,其下标为column1 space column2 space column3,value为column4。
现在在file2
上,我们需要通过执行a
来匹配数组中file1
的那些行,这将为我提供所有这些行(我们需要column4的值)在file2
中,其下标与(($1 FS $2 FS $3) in a) {print $0, a[$1 FS $2 FS $3]}
中的一个相同。