小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

關于Linux的grep -f命令,我以為我發(fā)現(xiàn)了bug

 育種數(shù)據分析 2021-11-18

關于Linux的grep -f命令,我以為我發(fā)現(xiàn)了bug #2021.8.5

前天的送書活動(留言送書 | 《統(tǒng)計之美》--體會統(tǒng)計的魅力)結果出來了,5位中獎人員,快來聯(lián)系我吧:


開始我的魔幻的一天:

?

今天,我以為我發(fā)現(xiàn)了Linux的grep的bug,最后竟然發(fā)現(xiàn)是windows和linux系統(tǒng)的換行符不一樣,知道真相的我留下了不學無術的眼淚。

?

事情是這個樣子的:

今天,我像往常一樣提取基因組的樣本,我有一堆樣本的ID,需要從所有的基因型的文件中提取出來。

以前我都是使用R語言,將基因型數(shù)據讀進去,將所要提取的ID文件讀進去,然后,我就有很多方法提取了 ,比如用match匹配位置,然后提取寫出。比如用merge或者left_join提取寫出。比如用%in%提取寫出。

?

我有很多方法處理它,但是我今天想用grep函數(shù),因為我知道grep -f file1 file2可以根據file1的內容提取篩選file2.

?

為什么我今天不用R語言處理了呢?

?

因為今天的基因型數(shù)據有點大,有90G,這個數(shù)據讀到R中只為了篩選其中的幾十行數(shù)據,不地道呀,太不地道了,雖然我們的服務器內存大,但是不是這樣玩的,同事會投訴我濫用計算機資源的,我沒有挖礦,為何用這么多資源?還不是編程水平差嗎!想到這里,我再次流下了不學無術的眼淚。

?

于是,我就開始準備文件,需要提取的樣本編號是這樣的:

$ cat id1.txt
Sample_ID
202797280021_R04C03
202817020006_R03C01
202817020006_R10C03
202817020009_R02C02
202817020009_R20C01
202817170002_R07C02
202817170002_R11C01
202817170002_R11C03
202817170002_R13C03

原始的基因型數(shù)據,第一列是這樣的,剩余的列都是進行數(shù)據,有1000多萬位點。

說時遲那時快,我直接寫下代碼,是時候展示真正的實力了:

$ grep -f id1.txt total.txt >re_id1.txt
$ wc -l re_id1.txt
0

什么都沒有!這不科學,我應該能提取出來的,應該都在文件中的,于是我用其中的一個基因型ID測試:

$ grep 202817020006_R10C03 total.txt
202817020006_R10C03

匹配出來了!

單個樣本可以匹配出來,多個樣本無法匹配出來,這是什么原因,我不僅陷入了沉思……

于是我開始了baidu,bing,google,查遍全網,也沒有找到原因。

沒有找到原因,我就模擬一個數(shù)據,自己測試一下吧,看看grep -f file1 file2是不是如我理解的那樣:

(base) [dfei@bogon ~]$ cat file1
2
4
e
(base) [dfei@bogon ~]$ cat file2
a1
b2
c3
d4
e5

如上所述,我模擬了兩個文件,一個是另一個的子集,匹配結果如下:

(base) [dfei@bogon ~]$ grep -f file1 file2
b2
d4
e5

可以看到,例子是沒問題的,grep -f用起來是666的。為何我實際分析時會報錯呢?我繼續(xù)全網搜索。

我看了grep的參數(shù),有一個-F的參數(shù),可以忽略正則表達式字符,直接用原始字符進行匹配,類似R中的fixed =T,我好像發(fā)現(xiàn)了新大陸,迫不及待試了一下:

[dengfei@localhost test]$ grep -F -f id1.txt total.txt >re_id1.txt
[dengfei@localhost test]$ wc -l re_id1.txt
0

沒有變化。



……漫長的分割線……



問題解決

原因是:windows和Linux換行符不一樣所致。

cat -A name.txt
Sample_ID^M$
202797280021_R04C03^M$
202817020006_R03C01^M$
202817020006_R10C03^M$
202817020009_R02C02^M$
202817020009_R20C01^M$
202817170002_R07C02^M$
202817170002_R11C01^M$
202817170002_R11C03^M$

可以看到,我的文件每一行的分隔符是^M$,這個是windows的換行符。而Linux是不支持它的,需要用dos2unix才可以進行后續(xù)的分析。

「代碼解決:」

dos2unix name.txt

然后再運行:

grep -f id1.txt total.txt >re_id1.txt

就匹配成功了。

那就順便整理一下grep的用法吧

基本用法:

grep name list name: 為需要匹配的字符 list:為文件

1,直接查找

grep phoenix sample2

直接在sample2文件中,顯示有phenoix的行

2,查找多個文件

grep phoenix sample1 sample2 sample3

在sample1,sample2,sample3三個文件中查找匹配到phoenix的行,并顯示

3,查找所有文件(支持通配符)

grep phenoix sample*
grep phenoix *

4,忽略大小寫 -i

grep -i phenoix *

5,遞歸查找,-r,查找當前文件夾的所有文件,包括所有子文件中的文件

grep -r phenoix *

6,反向顯示 -v,顯示不匹配的行

grep -v phenoix *

7,打印所有匹配的行,要全部匹配,而不是包含關系 -x

grep -x phenoix *

這里,只打印 phenoix的行,aphenoix是不打印的,因為不是完全匹配

8,僅顯示匹配的文件名稱,而不是所在的行 -l

grep -l phenoix *

9,顯示匹配的個數(shù) -c,類似uniq -c

grep -c phenoix *

10,顯示匹配所在的行號,類似cat -n

grep -n phenoix *

11,匹配單詞,而不是所有包含的行 -w

grep -w phenoix *

12,將匹配模式放到文件中 -f

grep -f file1 file2

會匹配file2中所有包括file1的行。注意:

  • file1和file2要編碼一致,可以用file查看
  • file1和file2行結尾符號一致,可以用cat -A查看,如果不一致,用dos2unix命令編一下
  • 匹配時,如果是單詞,可以加-w,這樣就不會匹配非單詞
  • 可以和-v一起使用,反向過濾
  • -F,當有通配符是.*,-F將其作為固定字符,不會對其轉義

    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多