我确实有以下情况:
文件 1 看起来像:
A
B
C
文件2看起来像:
chr1 \t 1234523 \t A
chr3 \t 1234231 \t A
chr6 \t 121233 \t A
chr1 \t 1126685 \t B
chr1 \t 15834523 \t B
chr4 \t 12345647 \t C
chr12 \t 1456523 \t C
我想得到输出:
A \t 3
B \t 2
C \t 2
我知道我可以这样做
grep A File2 | wc -l
但是,我需要对 File1 中的每一行(700)执行此操作。
我怎样才能自动化呢?
答案1
假设\t
s 实际上是制表符,并且出现在同一列上,并且 A 只匹配 A,不匹配 AA。让a
为包含 A、B、C 的文件和b
您要计算匹配项的文件(您提供的第二个文件)。
首先,您需要仅从 中获取可能的匹配项
b
,而忽略其他所有内容。这是 的第三列b
,所以我们可以使用cut
it 来剪切文件的一部分切-f 3 b
然后,您需要将其转换为出现次数及其计数的列表:您可以
uniq
在输出上进行排序并用于对这些次数进行计数cut
排序|优衣库-c
最后,你这样做是为了全部中的值
b
,但您只需要来自 的值a
。您可以使用join
它在公共字段上连接两个不同的文件(在本例中,第一个也是唯一的字段a
(似乎默认情况下这样做)和第二个字段(2
)b
,这是第二个文件(-2
)连接 -2 2 a 结果-b
您可以通过几种不同的方式链接它,一种可能的方法是使用来自bash
进程替换的命名管道:
join -2 2 a <(cut -f 3 b | sort | uniq -c)
这至少应该比单独的 grep 更好,因为您只处理 b 三次(删除其他列、sort
和uniq
),然后我想连接只会读取每个文件一次,因为它需要对输入进行排序。当然,这依赖于我所做的假设(并且您还必须进行排序a
,但这只是<(sort a)
代替a
之前未排序的情况。
答案2
从示例输入来看,您希望对制表符分隔记录的最后一个字段中的每个不同值进行计数。这是执行此操作的 awk 片段。
awk -F '\t' '
{++a[$NF]}
END {for (x in a) {print x "\t" a[x]}}
' File2
答案3
你可以用 while 循环来做到这一点
while read arg < FILE1; do echo -n -e "$arg\t"; grep "$arg" FILE2 | wc -l; done
这将读取 FILE1,并且对于每一行,for 循环都会将字符串存储到变量 $arg 中。
然后它将回显 $arg (-n 表示不在末尾插入行返回 (\n),-e 表示执行转义字符)。
然后它将显示在 FILE2 中找到 $arg 的出现次数。