轉(zhuǎn)錄組分析實戰(zhàn)第一天就踩的坑——sed與換行符的恩怨

題目是這樣的:

統(tǒng)計SRR1039510_1.fastq.gz堿基總數(shù) 1575000

由于上一題已經(jīng)列出了該文件中所有的序列

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | head
TGGGAGGCTGAGGCAGGAGAATCACTTAAACCTGGGAGGCAGAGGTTACAGTGAGCCGAGATT
AAAGAAGGCGACAGTGAGAAGGAGTCCGAGAAGAGTGATGGAGACCCAATAGTCGATCCTGAG
CTGCTGGGCCCCAAGGTCCTCCTGGTCCCAGTGGTGAAGAAGGAAAGAGAGGCCCTAATGGGG
CTTGGCTGCAGCCATCCCGCTTAGCCTGCCTCACCCACACCCGTGTGGTACCTTCAGCCCTGG
TGAGACAGGTAATTCAGTATAGTAGATTAATATTTTTAATATATATTTTCCCTTAAGATTTCC
ATTTCTCAGTGTAGAAATCATGTCTTCTTAATTGCTGAACCTTACTGCAAAAACTTGTGATGT
ATCAAGAATACCAAAACAGTTTCCTAATATACAGTATTTGAAAGTGCTTGCCATATTGGCTCT
CTCATTTTCATCTTCACCATCAACAGAGAGAGCAGCATACTTGCTTGCAGAACTGAACTTAGA
TCCAACCGCAGCTTGGCATCTTCGGTGGCCTGCAGCTCGTCCTCCAGCTCTTCCAGCTGCGTC
CGGCCTCCCAAAGTGCTGGGATTACAGGCATGAGCCACCGCGCTCTGCGAGGTACTTTTTCTA

于是我想,這還不簡單,直接wc -c

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | wc -c
1600000

但是,這居然和答案不對!居然多統(tǒng)計了25000.。。。等等,25000不就是第一題統(tǒng)計多少讀長的答案嗎

$ zcat SRR1039510_1.fastq.gz | grep '@SRR'| wc -l
25000

插播一點題外話,昨天“小二黑”直接統(tǒng)計行數(shù)

$ zcat SRR1039510_1.fastq.gz | wc -l
100000

老師說,再計算一下就好:每4行一個read,除以4就好了。于是我聯(lián)想起之前“萌哥”講過bc這個命令,還自己搞了一個“花樣”出來:

$ echo $(zcat SRR1039510_1.fastq.gz | wc -l)
100000
$ echo $(zcat SRR1039510_1.fastq.gz | wc -l)/4
100000/4
$ echo $(zcat SRR1039510_1.fastq.gz | wc -l)/4 | bc
25000

這姑且不說。

多統(tǒng)計出來25000個堿基,看起來似乎是每一行多統(tǒng)計了一個字符,那么多出來的這個字符是什么呢?聯(lián)想一下之前在某處似乎聽過,每行末尾的換行符是會計算進去的。于是我cat -A了一下。

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | cat -A | head
TGGGAGGCTGAGGCAGGAGAATCACTTAAACCTGGGAGGCAGAGGTTACAGTGAGCCGAGATT$
AAAGAAGGCGACAGTGAGAAGGAGTCCGAGAAGAGTGATGGAGACCCAATAGTCGATCCTGAG$
CTGCTGGGCCCCAAGGTCCTCCTGGTCCCAGTGGTGAAGAAGGAAAGAGAGGCCCTAATGGGG$
CTTGGCTGCAGCCATCCCGCTTAGCCTGCCTCACCCACACCCGTGTGGTACCTTCAGCCCTGG$
TGAGACAGGTAATTCAGTATAGTAGATTAATATTTTTAATATATATTTTCCCTTAAGATTTCC$
ATTTCTCAGTGTAGAAATCATGTCTTCTTAATTGCTGAACCTTACTGCAAAAACTTGTGATGT$
ATCAAGAATACCAAAACAGTTTCCTAATATACAGTATTTGAAAGTGCTTGCCATATTGGCTCT$
CTCATTTTCATCTTCACCATCAACAGAGAGAGCAGCATACTTGCTTGCAGAACTGAACTTAGA$
TCCAACCGCAGCTTGGCATCTTCGGTGGCCTGCAGCTCGTCCTCCAGCTCTTCCAGCTGCGTC$
CGGCCTCCCAAAGTGCTGGGATTACAGGCATGAGCCACCGCGCTCTGCGAGGTACTTTTTCTA$

然后突然想起

$ zcat SRR1039510_1.fastq.gz |head
@SRR1039510.1 HWI-ST177:290:C0TECACXX:1:1101:1373:2104 length=63
TGGGAGGCTGAGGCAGGAGAATCACTTAAACCTGGGAGGCAGAGGTTACAGTGAGCCGAGATT
+SRR1039510.1 HWI-ST177:290:C0TECACXX:1:1101:1373:2104 length=63
HJJJIJJJJJJJJIJJJGHHIJIIIIIIJJEHGGIJGIJIJJIJHHHGGFFDFFFDEDDDBDC
@SRR1039510.2 HWI-ST177:290:C0TECACXX:1:1101:1340:2124 length=63
AAAGAAGGCGACAGTGAGAAGGAGTCCGAGAAGAGTGATGGAGACCCAATAGTCGATCCTGAG
+SRR1039510.2 HWI-ST177:290:C0TECACXX:1:1101:1340:2124 length=63
HJJJJJJJJJJJIJIIGIJJJJGJHJJJHHDFFFE@CEEEDDDDDDDDDDDDDDDBDDDDDDD
@SRR1039510.3 HWI-ST177:290:C0TECACXX:1:1101:1273:2183 length=63
CTGCTGGGCCCCAAGGTCCTCCTGGTCCCAGTGGTGAAGAAGGAAAGAGAGGCCCTAATGGGG

人家這里都告訴你每個read的長度是63,于是計算一下

$ echo 63*25000 |bc
1575000

果然就是正確答案。

說明:1,的確每行多統(tǒng)計了一個字符;2,且多統(tǒng)計的是行末的換行符。

然后我想怎么把準確的數(shù)字統(tǒng)計出來,那就需要把行末的換行符去掉。于是:

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | sed 's/\n//g' | wc -c
1600000

發(fā)現(xiàn)并沒有刪除掉換行符。于是陷入了各種嘗試,驗證,懷疑……

最后在網(wǎng)上搜到了一個答案:

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | sed -e ':a;N;s/\n//g;ta' | wc -c
1575001

這個。。。似乎是去掉換行符了,但是。。怎么還多一個。。。

于是又開始猜想,可能是最后一個換行符沒有刪掉,為什么沒有刪掉呢,可能這個命令不適合我,需要再調(diào)整。于是又學習了這里面的冒號:t a N都是些什么意思,怎么用的。。。。

然后發(fā)現(xiàn),確實沒有錯,就是最后一個換行符沒有刪掉。

zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | sed -e ':a;N;s/\n//g;ta' | cat -A 
刷屏中……GATGGGGATCTGGCTCATGTCCAAAGGTGCAATATCAAGGAAGGGCAGGCGTGATGGCTTATTTGTTTTGTATTCAATGAATTTACACAGTCTCAGATTATCTCCTAACTCCCCACAAGACACTTATTTATTCCAAAGAAAGAACCAAAACTCCTGATGATGAAGGCCAGGGCCTCACGGGGCACCTCTCGGTTCAGGAAGAACTTCCATCGCTCGGCTGTTGGACCGGAACCAGGATGCAACTGAGGACACTGACGTGCAGAACATGAGGTGGCTTCTTGCAGTTCTCCCTGTAGACCCACGATACCAGCTGTCGGTTTTGTCAATGAAGTCCAGGCTCAGGCCCCCGGGCCCGATCATGGCCCCAGTCCGCACAGAGCGCCCGGCCCTGGCCGGTGTGGACAGAACTGGGGGCAAAAACAAAAAAGAAGGAAGGAAGGAAAGAAAGAAATGGGTAT$

N在這里把所有的序列合成1行了,然后再輸出的,最后帶一個換行符。

到這里徹底放棄sed了,腦霧之后想起tr還可以用,于是又嘗試一下。

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | tr -d '\n' | wc -c 
1575000

終于得到了正確答案!

但是為什么sed替換掉換行符,最后一個還留著呢?為什么不用標簽來寫script就一個也替換不掉呢?

因為(參考:http://yysfire.github.io/linux/sed-usage-summary.html 或者https://blog.csdn.net/u011729865/article/details/71773840

sed 維護著兩個數(shù)據(jù)緩存區(qū):模式空間和保留空間。兩者均被初始化為空。

sed 對輸入的每一行運行一次如下所述的執(zhí)行周期:首先,sed 從輸入流中讀入一行,并刪除行末的換行符,將此行的內(nèi)容放入模式空間。然后,腳本里的命令被執(zhí)行;可以對每一個命令指定地址(地址相當于一種條件,只有條件被滿足,才會執(zhí)行緊跟其后的命令。當?shù)竭_腳本的結(jié)尾,模式空間的內(nèi)容(如果之前行末的換行符被刪除,此時會被加回來)被寫入到輸出流(除非使用了選項'-n')。然后,對下一行開始下一個執(zhí)行周期。

標簽的使用參考上述地址或者:http://blog.chinaunix.net/uid-20943515-id-403.html

man一下sed,發(fā)現(xiàn)有個-z選項,可以用空字符作為每行的分割

-z, --null-data

              separate lines by NUL characters
              
              
$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | sed -z 's/\n//g'| wc -c 
1575000

其實不糾結(jié)于sed,可以用awk來實現(xiàn):

$ zcat SRR1039510_1.fastq.gz | sed -n '2~4p' | awk '{print $0}' ORS='' | wc -c
1575000
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容