刘小泽写于19.3.10
继续学习单行命令
Case1 - awk
如果有一个文件包含两列,一列是尝试(attempt)次数,一列是成功(success)次数,我们想计算总的成功率,也就是自定义输出结果。
逻辑上很简单,需要知道总的尝试次数和总的成功次数,那么怎样获得这两个值呢?也就是说,我们怎样将第一列累加并赋值给attempt,第二列累加值给success?
# 创建一个新的变量就需要先用BEGIN指定,然后再END中输出
awk 'BEGIN { sum_attempt = sum_success = 0; }{ sum_attempt += $1 ; sum_success += $2} END {print "Attempt: ", sum_attempt, "Success: ", sum_success, "Rate: ", sum_success/sum_attempt*100,"%" }' test.txt
这样结果输出的就会是类似这样:
Attempt: 30
Success: 15
Rate: 50%
如果有一个文件,第一行是头信息,我们想去掉第一行,然后只选出来其中的第4列:
awk 'NR>1 && NF == 4' test.txt
其中NR指的是行号(Number of row),NF指的是列号(Number of field)
Case2 - grep
如果我们要找到以“bioplanet”开头的记录,需要使用^
grep '^bioplanet' test.txt
Case3 - sort
如果有一个文件的第2列是染色体编号,第3列是染色体前起始位置,现在我们想先根据染色体编号排序,再按照起始位置排序,就可以利用sort
sort -k 2n -k 3n chr.txt
-k
就是指定按照哪一列进行排序,但是需要注意的是,默认按照ASCII码排序,即100小于11,于是如果要按照真实阿拉伯数字大小排序,需要加上参数-n
Case4 - uniq
如果一个文件中第3列包含许多重复的字符,例如分组信息A、B、C三组,看看每一条记录在哪个分组信息中,最后计算各个分组信息的情况
awk '{print $3}' test.txt | sort | uniq -c
# 这里-c表示count
一般uniq与sort是分不开的,并且是先sort后再uniq
如果现在有两个文件,例如:
$ cat test1.txt
A1BG RXRA
A2M-AS1 GABP
A2M SRF
A4GALT GABP
AAAS CTCF
$ cat test2.txt
ACAT2
A1BG
ACTA1
ACTA2
ADM
AEBP1
我们想找他们的第一列是否有相同的结果
首先就是将这两个文件合并在一起,然后取出第一列,并排序,排序后找共同值【也可以理解成为取两文件某一列的交集 intersection】
$ cat test1.txt test2.txt | awk '{print $1}' | sort | uniq -d >intersection
# 结果就是A1BG
这里看到用了-d
的参数,意思就是只输出出现次数大于1次的行
【如果要取两个文件的并集 union,就是去掉它们共同有的成分,直接把uniq的-d
参数去掉即可】
$ cat test1.txt test2.txt | awk '{print $1}' | sort | uniq >union
A1BG
A2M
A2M-AS1
A4GALT
AAAS
ACAT2
ACTA1
ACTA2
ADM
AEBP1
如果想找在第一个文件中存在而在第二个文件中不存在的行,需要先找交集(上面已经完成了),然后从第一个文件中剔除交集的部分
$ awk '{print $1}' test1.txt | cat - intersection | sort | uniq -u >test1-only
A2M
A2M-AS1
A4GALT
AAAS
注意到cat
后面多了一个-
,意思是将前面awk的标准输出结果存到-
中,方便调用;另外这里用了-u
的参数,意思是只输出出现一次的结果
Case5 - join
这个用法和R中的merge差不多,就是根据两个文件某一列,将共同的行输出,利用join
可以实现,但使用前必须进行sort
# 这里都按第一列进行排序
$ sort -k1 test1 >sort.test1
$ sort -k1 test2 >sort.test2
$ join sort.test1 sort.test2
# 结果就是 A1BG RXRA,可以看到,除了输出了二者第一列的交集A1BG,还输出了后面的内容
join
根据第一列进行融合,如果要指定按照其他列,可以join -j
更多情况是:要比较的两个文件列数不一致,前面例子中都是根据第一列,但现实中可能根据第一个文件的第二列,根据第二个文件的第三列,然后找他们的共同之处,并提取出共同的行
# 首先还是要将文件根据不同的列进行sort
$ sort -k2 a1> sort.a1
$ sort -k3 b1> sort.b1
$ join -1 2 -2 3 sort.a1 sort.b1
这里的-1 2 -2 3
就是指的利用第一个文件的第2列和第二个文件的第3列
来看一个更加贴近实际的例子:
$ cat >exp.bed
chr1 26 39
chr1 32 47
chr3 11 28
chr1 40 49
chr3 16 27
chr1 9 28
chr2 35 54
chr1 10 19
$ cat >exp_lengths.txt
chr1 58352
chr2 39521
chr3 24859
目标:把长度信息贴在bed文件每一行后面
$ sort -k1 exp.bed >sort.exp.bed
$ sort -k1 exp_lengths.txt >sort.exp_lengths.txt
$ join -1 1 -2 1 sort.exp.bed sort.exp_lengths.txt
chr1 10 19 58352
chr1 26 39 58352
chr1 32 47 58352
chr1 40 49 58352
chr1 9 28 58352
chr2 35 54 39521
chr3 11 28 24859
chr3 16 27 24859
欢迎关注我们的公众号~_~
我们是两个农转生信的小硕,打造生信星球,想让它成为一个不拽术语、通俗易懂的生信知识平台。需要帮助或提出意见请后台留言或发送邮件到Bioplanet520@outlook.com