grep:最快的文本搜索工具
grep就是在文本提取和匹配上最快的工具,因為它只有一個目標,在每一行找匹配的內容,并且在這個任務上沒有其他程序比他是做的更好。
繼續以擬南芥基因組和注釋文件作為練習對象(下載方式見我上一篇文章)。
- 在注釋文件中查找某一個基因如AT5G25475
$ grep "AT5G25475" TAIR10_GFF3_genes.gff | head -5
Chr5 TAIR10 gene 8867797 8869821 . - . ID=AT5G25475;Note=protein_coding_gene;Name=AT5G25475
Chr5 TAIR10 mRNA 8867797 8869652 . - . ID=AT5G25475.1;Parent=AT5G25475;Name=AT5G25475.1;Index=1
Chr5 TAIR10 protein 8867920 8869492 . - . ID=AT5G25475.1-Protein;Name=AT5G25475.1;Derives_from=AT5
G25475.1
Chr5 TAIR10 five_prime_UTR 8869493 8869652 . - . Parent=AT5G25475.1
Chr5 TAIR10 CDS 8869391 8869492 . - 0 Parent=AT5G25475.1,AT5G25475.1-Protein;
- 希望搜索AT5G25475但是不包含CDS(-v:反向選擇)
$ grep "AT5G25475" TAIR10_GFF3_genes.gff | grep -v 'CDS' | head -5
Chr5 TAIR10 gene 8867797 8869821 . - . ID=AT5G25475;Note=protein_coding_gene;Name=AT5G25475
Chr5 TAIR10 mRNA 8867797 8869652 . - . ID=AT5G25475.1;Parent=AT5G25475;Name=AT5G25475.1;Index=1
Chr5 TAIR10 protein 8867920 8869492 . - . ID=AT5G25475.1-Protein;Name=AT5G25475.1;Derives_from=AT5
G25475.1
Chr5 TAIR10 five_prime_UTR 8869493 8869652 . - . Parent=AT5G25475.1
Chr5 TAIR10 exon 8869391 8869652 . - . Parent=AT5G25475.1
反向選擇與head,wc連用的時候,可以先排除一些注釋信息('#'),再操作。
- 基因組中查找某一段特定序列并查看上下文(-A n:顯示后n行-B,n:顯示前n行,-C= -A,-B)
$ grep -A 2 'TTATTGTTGTTAAGAAAAAAGG' TAIR10_chr_all.fa
GTCGCCGCATTTTGTAATGCATACTTGTCTCTGTTATTGTTGTTAAGAAAAAAGGAGCACAAGTTGAGCAATGAAATAA
AATTGAATGGGCTAATGCTACAATCCCTTTTAATCAGCACAAATTGAATTAAGTTGAGGTGATTAAAAGGGATCTATCT
AGGTTTGTGGCAACAATAATAAAATGGAATCACAAACAAACTCCATAAAGGTAACCCTAAAAAAGGAGGGAAATCGCAA
- 在基因組中統計某一段序列出現的個數 (-c : count)
$ grep 'TTATTGTTGTTAAGA' TAIR10_chr_all.fa -c
2
# 其實還可以接wc -l
$ grep 'TTATTGTTGTTAAGA' TAIR10_chr_all.fa | wc -l
2
- 只返回匹配到的內容
$ grep 'TTATTGTTGTTAAGA' TAIR10_chr_all.fa -o
TTATTGTTGTTAAGA
TTATTGTTGTTAAGA
如果你想查找一個以AT5G254開頭以1結尾的基因,你就要用到強大的正則表達式。
$ grep 'AT5G254.*5$' TAIR10_GFF3_genes.gff
Chr5 TAIR10 gene 8834206 8837248 . + . ID=AT5G25415;Note=protein_coding_gene;Name=AT5G25415
Chr5 TAIR10 gene 8848549 8848986 . + . ID=AT5G25425;Note=protein_coding_gene;Name=AT5G25425
Chr5 TAIR10 gene 8867797 8869821 . - . ID=AT5G25475;Note=protein_coding_gene;Name=AT5G25475
awk: 強大的文本操作工具
在上篇文章中,我使用了許多linux基本命令去完成一些瑣碎的生信數據處理任務。而在awk眼中,這些任務它一個人就能搞定。awk:"我要打十個"
awk的工作原理
awk擅長處理表格形式的數據。它逐行從文本中讀取數據,將整行數據(record)定義為$0
,然后根據指定的分隔符,將各列數據(record)分別定義為$1
,$2
,$3
然后使用如下結構處理數據
pattern1 {action1};pattern2 {action2};....
形如if函數,當滿足pattern時執行后接的action.
注意:
- 如果沒有定義pattern,則直接執行action;
- 如果沒有提供action,則直接輸出滿足pattern的內容
基本用法
首先讓我們用awk實現cat
,cut
這些命令。
- cat
$ awk '{print $0}' TAIR10_GFF3_genes.gff | head -2
Chr1 TAIR10 chromosome 1 30427671 . . . ID=Chr1;Name=Chr1
Chr1 TAIR10 gene 3631 5899 . + . ID=AT1G01010;Note=protein_coding_gene;Name=AT1G01010
- cut
$ awk '{print $1,$4,$5}' TAIR10_GFF3_genes.gff | head -2
Chr1 1 30427671
Chr1 3631 5899
awk除了能輸出指定列,還能重排,甚至換一種分隔符,比cut更加強大
$ awk '{print $4","$5","$1}' TAIR10_GFF3_genes.gff | head -1
1,30427671,Chr11
進階功能
除了這些簡單的功能以外,awk還支持
- 算術運算(+,-,*,/,%,),
- 邏輯運算(==,!=,<,>,>=,<=),
- 或與非(&&,||,!),
- 還可以進行模式匹配(ab,a!b)。
當然知道有這些內容還不夠,我們還要在實際中使用。
實例:找到長度大于10kb且在一號染色體的注釋內容
$ awk '$5 - $4 > 10000 && $1 ~ /Chr1/' TAIR10_GFF3_genes.gff | head -5
Chr1 TAIR10 chromosome 1 30427671 . . . ID=Chr1;Name=Chr1
Chr1 TAIR10 gene 373335 386847 . + . ID=AT1G02080;Note=protein_coding_gene;Name=AT1G02080
Chr1 TAIR10 mRNA 373335 386847 . + . ID=AT1G02080.1;Parent=AT1G02080;Name=AT1G02080.1;Index=1
Chr1 TAIR10 protein 373335 386682 . + . ID=AT1G02080.1-Protein;Name=AT1G02080.1;Derives_from=AT1
G02080.1
Chr1 TAIR10 mRNA 373501 386846 . + . ID=AT1G02080.2;Parent=AT1G02080;Name=AT1G02080.2;Index=1
練習題: 請找到長度小于1kb,在2號或者三號染色體注釋
awk還有兩個特殊模式BEGIN,END,顧名思義就是在操作開始或/和結束后才執行的操作。
實例: 計算長度1號染色體cds的平均長度.
$ awk 'BEGIN {s = 0;line = 0 } ;$5 - $4 > 10000 && $1 ~ /Chr1/ { s += ( $5 - $4 );line += 1}; END {print "mean=" s/line
}' TAIR10_GFF3_genes.gff | head -5
mean=227598
練習題:請計算2號染色體和3號染色體的CDS的平均長度。
awk內部有許多特殊變量,如NR,表示當前所在的行數
實例: 顯示第3-5行數據類似于head -n5 | tail -n2
$ awk ' NR>=3 && NR <=5 {print $0}' TAIR10_GFF3_genes.gff
Chr1 TAIR10 mRNA 3631 5899 . + . ID=AT1G01010.1;Parent=AT1G01010;Name=AT1G01010.1;Index=1
Chr1 TAIR10 protein 3760 5630 . + . ID=AT1G01010.1-Protein;Name=AT1G01010.1;Derives_from=AT1
G01010.1
Chr1 TAIR10 exon 3631 3913 . + . Parent=AT1G01010.1
awk還有一個類似于Python的字典結構,叫做關聯數組(associative array).使用這個我們就可以實現cat xx.file cut -f '2'| sort | uniq -c | sort
類似的操作
$ awk '$1 ~ /Chr1/ { feature[$3] += 1};\
END { for (k in feature) print k "\t" feature[k]}' TAIR10_GFF3_genes.gff
pseudogene 241
ncRNA 144
exon 58048
chromosome 1
snRNA 2
protein 9263
...
除此之外,他還可以使用if,for,while,還有許多常用的函數(見下表),所以說awk真的可以當做一門編程語言學習了。不過如果真的需要特別多的處理步驟,其實你可以直接使用Pyhton/perl等更強大的編程語言了。
函數 | 功能 |
---|---|
length(s) | s的長度 |
tolower(s) | 轉成小寫 |
toupper(s) | 轉成大寫 |
substr(s,i,j) | 返回s的i-j部分 |
split(s,x,d) | 根據分隔符d分隔數據,賦值給x |
sub(f,r,s) | 根據正則f從r中提取數據到s |
番外:bioawk 生物版awk
雖然awk非常強大,但是如果它能夠自動識別我們生物數據格式(如GFF/GTF,FASTQ/FASTA/,BED),自動分配record該多好。
請大家膜拜一下Heng Li,然后去下載bioawk
具體用法就不細說了。可以將bioawk代替awk重復前面的練習和實例。
sed: 流處理工具
sed的功能同樣也很強大,但是這里只負責介紹兩個常用的模塊:文本替換和顯示特定行。
假如有一個文件a.txt如下內容:
chrom1 123 456
chrom2 123 456
chrmo3 123 456
我們可以很方便的使用sed將chrom替換成chr:
# sed 's/pattern/replacement/' file
sed 's/chrom/chr/' a.txt
chr1 123 456
chr2 123 456
chr3 123 456
假設我們只想打印第2行,處理可以用head加tail或者awk完成,還可以用sed
#sed -n 'n1,n2p' file.txt
# -n 只輸出編輯部分;p打印;n1,n2從以n1到n2
sed -n '2p' a.txt
由于許多sed的功能都和前面的awk和grep沖突,所以這里只介紹了這兩個功能。
如果想了解更多 awk和sed的功能,可以到http://dongweiming.github.io/sed_and_awk進入深入的學習。