我用 Python 写了一个脚本,但它的速度不够快,无法完成这项工作。我认为逐行处理会更好。
我有两个文件,每个文件有两列,可能有数亿行(生物信息学)。这两个文件(文件 1、文件 2)类似,以制表符分隔,第一列包含字母和数字字符串,第二列包含整数。每个文件的标题都是name
, 。count
我需要生成一个制表符分隔的文件,其中:每行的第一个条目来自列,但只有同时在和name
中的名称,第二个条目是来自文件 1 的;第三个条目是来自的,保留标题。file1
file2
count
name
count
name
file2
经过大量阅读后,这是我的尝试:
awk '(NR == FNR) {
n0[$1] = 0;
n1[$1] = 0;
next
} {
if($1 in n0) {
n2[$2] = 0
}
} END {
for (i in n0) (j in n1) (k in n2) {
print i,"\t",j,"\t",k
}
}' file1 file2
所以很明显我真的不知道创建数组要做什么(我不确定它们是否可以是二维的,所以我尝试使用三维)。
如果有人可以使用与上面相同的基本流语法来纠正 awk 脚本,那就太好了,非常感谢。
另外,要将其转换为可执行的 .sh 文件,应该怎么做?
从两个文件第一列的元素中(只有两个文件中都存在的元素)找到第一列中两个文件值的交集,然后
答案1
如果你的输入按第一列排序,那么效果会更好,因为你可以直接使用join
命令:
$ cat foo
a 1
b 2
c 3
d 4
$ cat bar
b 1
d 4
e 5
n 2
$ join -t $'\t' <(sort foo) <(sort bar)
b 2 1
d 4 4
无论如何,我建议进行排序 - 如果没有排序,您可能会查看O(m*n)
操作,但是如果进行排序,则O(m*log(m) + n*log(n) + min(m,n))
进行操作 - 如果您优化方法而不是使用的语言,它应该可以节省您一段时间。
使用awk
,你可以使用单个数组:
awk 'NR==FNR { n[$1] = $2; next } ($1 in n) {print $1, n[$1], $2}' foo bar
如果是的话,这也应该相当快$i in n
。
答案2
和bash
:
假设file1
:
abc123 123456
def456 789123
ghi789 456789
和file2
:
abc123 789123
这将输出file3
:
abc123 123456 789123
#!/bin/bash
while read line1; do
var1=$(echo $line1 | tr '\t' '\n')
while read line2; do
var2=$(echo $line2 | tr '\t' '\n')
if [ "${var1[0]}" == "${var2[0]}" ]; then
printf "%s\t%s\t%s\n" "${var1[0]}" "${var1[1]}" "${var1[2]}"
fi
done < file2
done < file1