2015-11-13 39 views
1

连接多个TSV文件中选择列我有类似以下在bash

"gene_id" "Pattern1" "Pattern2" "Pattern3" "Pattern4" "Pattern5" "MAP" "PPDE" 
"ENSG00000119771.13" 3.11528786599051e-18 2.52650109640992e-13 6.25109524320237e-09 0.345846257420197 0.654153736328455 "Pattern5" 1 
"ENSG0000.4" 1.75016991626305e-36 3.98804090894939e-19 0.63423772228367 3.8159144080782e-21 0.36576227771633 "Pattern3" 1 
"ENSG00000128567.15" 1.10722918612618e-23 7.62691311068806e-07 5.77031364194955e-06 5.13675840911147e-21 0.999993466995047 "Pattern5" 1 
"ENSG00000130182.6" 9.75717082221716e-22 1.27675651077242e-12 0.469972541094369 1.13677117238758e-12 0.530027458903217 "Pattern5" 1 
"ENSG00000131914.9" 3.1627489688037e-41 1.00274706758683e-22 0.0578584524816503 6.98718794692175e-22 0.94214154751835 "Pattern5" 1 

现在我想将它们加入到一个文件中,使我得到了一堆的制表符分隔文本文件

"gene_id" "Pattern5" "Pattern5" "Pattern5" "Pattern5" "Pattern5" 

其中每个Pattern5列来自一个文件。

我尝试了一些东西与

cut -f 6 <file> 

paste <file1> <file2> ... 

,但我无法正确地结合起来。

感谢您的帮助!

UPDATE: 我尽量给你一个可测试的例子作为输入这里:

<file1> 
gene_id Pattern1 Pattern2 Pattern3 Pattern4 Pattern5 
ENSG00000119771 1 2 3 4 5 
ENSG0000
ENSG00000128567 1 2 3 4 5 
ENSG00000130182 1 2 3 4 5 
ENSG00000131914 1 2 3 4 5 

<file2>   
gene_id Pattern1 Pattern2 Pattern3 Pattern4 Pattern5 
ENSG00000119771 6 7 8 9 10 
ENSG0000
ENSG00000128567 6 7 8 9 10 
ENSG00000130182 6 7 8 9 10 
ENSG00000131914 6 7 8 9 10 

<file3>    
gene_id Pattern1 Pattern2 Pattern3 Pattern4 Pattern5 
ENSG00000119771 11 12 13 14 15 
ENSG0000
ENSG00000128567 11 12 13 14 15 
ENSG00000130182 11 12 13 14 15 
ENSG00000131914 11 12 13 14 15 

和所需的输出将

gene_id Pattern5_file1 Pattern5_file2 Pattern5_file3 
ENSG00000119771 5 10 15 
ENSG0000
ENSG00000128567 5 10 15 
ENSG00000130182 5 10 15 
ENSG00000131914 5 10 15 

UPDATE2: 我想尽了办法Ed Morton:

awk ' 
BEGIN { FS=OFS="\t" } FNR==1{ARGIND++} 
{ genes[$1]; val[$1,ARGIND] = $5 } 
END { 
    for (gene in genes) { 
     printf "%s%s", gene, OFS 
     for (file=1; file<=ARGIND; file++) { 
      printf "%s%s", val[gene,file], (file<ARGIND?OFS:ORS) 
     } 
    } 
} ' $files 

但输出是不正确的格式:

ENSG00000128567 4 9 14 
ENSG00000130182 4 9 14 
ENSG00000119771 4 9 14 
gene_id Pattern4 Pattern4 Pattern4 
ENSG00000131914 4 9 14 
ENSG0000
+0

列索引也将是不错的文件名作为连接文件中的列标题例如 ''''gene_id“”“”“”“”“'''' – Max

+0

P.P.S.我有很多文件(〜200),所以我要求一个通用的解决方案,我只是在命令中插入一个文件列表 – Max

+0

注意到你试过剪切和粘贴,我没有看到任何排序或关联的尝试。那么第1列的gene_id是否与所有文件完全相同?所以我们不必担心匹配行。那么文件1,第1列的第7行与第200行文件中第1列第7行的值相同? – user454038

回答

2

尝试这一个

#!/bin/bash 

paste file1 file2 file3 | awk -v patternIdx=6 ' 

function printPattern(idx, isFirstLine) { 
    for (i = 1; i <= NF; ++i) { 
     if (i == 1) 
      printf "%s ", $i; 
     else if (isFirstLine && i % patternIdx == 0) 
      printf "%s_file%d ", $i, i/patternIdx; 
     else if (i % patternIdx == 0) 
      printf "%d ", $i; 
    } 
    printf "\n" 
} 
{ 
    if (NR == 1) 
     printPattern(patternIdx, 1); 
    else 
     printPattern(patternIdx, 0); 
}' 

patternIdx是Pattern5

+0

谢谢,那看起来很完美! – Max

1
for f in file1 file2 file3; do 
    cut -f 6 $f; done | 
awk '{if ($1~/Pattern5/) {printf("\n%s\t",$1)} else {printf("%s\t",$1)} };END{print ""}' | 
tail -n +2 

“Pattern5” 0.654153736328455 0.36576227771633 0.999993466995047
“Pattern5” 0.654153736328455 0.36576227771633 0.999993466995047
“Pattern5” 0.654153736328455 0.36576227771633 0.999993466995047

(我只是使用相同的数据file1-3。) 你也可以指定输入文件,如果他们是regularl y命名,带有glob,例如for f in myfiles*