2016-06-13 19 views
-1

我有兩個文件具有類似的結構(製表符分隔的和許多行,第3個減去第2列= 1)增加一列,看起來有點像這樣:具有部分匹配圖案從一個不同的文件

文件1:

1 170023 170024 A - 
1 170024 170025 T - 
1 170026 170027 A - 
1 170028 170029 G - 
1 170029 170030 C - 
1 170031 170032 C - 

文件2:

1 170023 170024 A 
1 170024 170025 T 
1 170025 170026 G 
1 170026 170027 A 
1 170027 170028 G 
1 170028 170029 T 
1 170029 170030 A 
1 170030 170031 G 
1 170031 170032 C 

我想從文件加2列4(字母僅列),以文件1.這在一般情況下,很容易與prpaste但問題是在兩個文件中列1-3不相同。換句話說,文件具有不同數量的行,並且文件2總是比文件1多(特別是,文件1中發現的列2和3中的所有數字也出現在文件2中,但是不是反之亦然)。我也知道如何在R中完成它,但是這些文件太大而無法在R中輕鬆處理,而且我需要爲十幾個文件完成任務。所以我想,bash或者任何命令行軟件都是解決這個問題的最有效的方法。

我確實想要做的就是添加文件2中第4列的字母,當且僅當文件2中的第1-3列完全匹配第1個文件中的第1-3列。由此,也沒有關係在4列和文件1.基於文件1的實施例的5發生什麼符號和上述文件2,所期望的輸出將是:

輸出:

1 170023 170024 A - A 
1 170024 170025 T - T 
1 170026 170027 A - A 
1 170028 170029 G - T 
1 170029 170030 C - A 
1 170031 170032 C - C 

我如果有人能幫助我,我會很高興。非常感謝您提前!

回答

1

我可以考慮並提供一個簡單的解決方案,使用joinawk。可能不是最有效的方法來解決它awk(可能會從專家爲此:)),但我能夠解決這個問題。

解決方案 - 1 -

所有你需要做的,是先用join不指定任何特定列加入上。它會根據常見的重複性列自動加入文件,在這種情況下,列爲1。然後在該輸出上,我們可以讓awk播放以打印符合您需要的那些行並格式化所需的列。

join file1 file2 | awk '{ if (($2==$6) && ($3==$7)) printf("%s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $8) }' 

製作我的輸出作爲

1 170023 170024 A - A 
1 170024 170025 T - T 
1 170026 170027 A - A 
1 170028 170029 G - T 
1 170029 170030 C - A 
1 170031 170032 C - C 

解決方案2: -

只使用純join

join -j 2 file1 file2 -o 1.1,1.2,1.3,1.4,1.5,2.4 

也會產生相同的輸出與您預期。

`join' writes to standard output a line for each pair of input lines that have identical join fields. 

上午引述爲joinman頁面內容如下

`-j FIELD' 
    Equivalent to `-1 FIELD -2 FIELD'. 

`-o FIELD-LIST' 

Otherwise, construct each output line according to the format in 
FIELD-LIST. Each element in FIELD-LIST is either the single 
character `0' or has the form M.N where the file number, M, is `1' 
or `2' and N is a positive field number. 

所以命令工作首先由通過柱2加入file1file2和打印從看到的輸出,所指示的所要求的列( 1.11.2,1.3, 1.4, 1.5, 2.4),其應被理解爲filecolumn。爲了更好地理解,我建議首先看到沒有-o選項的輸出,以及我如何從所看到的輸出構建輸出。

解決方案-3: -

使用plain'ol awk,其實我學到了一點它自己,而回答這個問題。

awk 'FNR==NR{a[$1 FS $2 FS $3]=$4;next} (($1 FS $2 FS $3) in a) {print $0, a[$1 FS $2 FS $3]}' file2 file1 

說明: -

  1. FNR==NR{a[$1 FS $2 FS $3]=$4;next}將上file2處理存儲陣列a的條目以標爲列1列2空間空間欄3和值作爲column4。

  2. 現在在file1,我們需要做(($1 FS $2 FS $3) in a) {print $0, a[$1 FS $2 FS $3]}以匹配file2從陣列中的行,這將給我所有的行(我們需要column4的值)file1,其下標是同一個從file2

+0

非常感謝!我仍然在運行分析(很多大文件),並將編輯此評論以報告它是如何實現的。 – AlexDeLarge

+0

@AlexDeLarge:這會很有幫助! – Inian

+0

由於我有製表符分隔的文件,並且新列也應該用製表符分隔,所以我使用了以下命令爲基礎的第三個解決方案:'awk'FNR == NR {a [$ 1「\ t」$ 2「\ t」 $ 3] = $ 4;下一個}(($ 1「\ t」$ 2「\ t」$ 3)in a){print $ 0「\ t」a [$ 1「\ t」$ 2「\ t」$ 3]}'file2 file1' 。再次謝謝你! – AlexDeLarge

相關問題