2017-07-17 215 views
1

我有三個文件,我想從中提取一些列並將它們粘貼到一個新文件中。這些文件不一定具有相同的行數。它們按照第一列中的值排序。從多個.csv文件中提取列並將它們合併爲一個

文件1具有以下結構:

col1;col2;col3;col4 
SAMPLE-1;1;1;1 
SAMPLE-2;1;1;1 
SAMPLE-3;1;1;1 
SAMPLE-4;1;1;1 

此文件由分隔 「;」代替 「」

文件2具有以下結構:

col5,col6,col7,col8 
SAMPLE-1_OTHER_INFO,2,2,2 
SAMPLE-2_OTHER_INFO,2,2,2 
SAMPLE-3_OTHER_INFO,2,2,2 

文件3具有以下結構:

col9,col10,col11,col12 
SAMPLE-1_OTHER_INFO,3,3,3 
SAMPLE-2_OTHER_INFO,3,3,3 
SAMPLE-3_OTHER_INFO,3,3,3 

輸出文件(summary.csv)應該是這樣的:

col1,col2,col4,col6,col7,col10,col12 
SAMPLE-1,1,1,2,2,3,3 
SAMPLE-2,1,1,2,2,3,3 
SAMPLE-3,1,1,2,2,3,3 
SAMPLE-4,1,1,,,, 

基本上所有三個文件的第一列都包含樣本標識符。 file1的'col1'應該是輸出文件的第一列。 col1中的標識符應該與file2和file3的col5和col9中的標識符匹配。比較時不應該考慮'_OTHER_INFO'部分。

如果匹配,應添加文件2和3的col6,col7,col10和col12值的信息。

如果沒有比賽,該行仍然應該在輸出文件,但最後四列應該是空的(如在這種情況下,「樣品4」)

我正打算執行此操作用awk或'cut/paste'命令。但是我不知道我應該如何尋找col1,col5和col9中的值之間的匹配。

+0

我會建議使用一些解釋的langauge像[蟒](https://stackoverflow.com/q (https://stackoverflow.com/questions/tagged/perl)或[ruby](https://stackoverflow.com/questions/tagged/ruby)。我相信Awk會有這種可能,使用這種語言之一應該會更容易。例如,在python中你可以使用[csv module](https://docs.python.org/2/library/csv.html),這是專門爲這樣的任務設計的。 –

回答

2

請嘗試下面,讓我知道這是否有助於你。

awk 'BEGIN{ 
       FS=";" 
      } 
    FNR==1{ 
       f++ 
      } 
    f==1 && FNR>1{ 
         a[$1]=$2","$4; 
         next 
        } 
    f>1 && FNR==1 { 
         FS="," 
        } 
    f==2 && FNR>1{ 
         sub(/_.*/,"",$1); 
         b[$1]=$2","$3; 
         next 
       } 
    f==3 && FNR>1{ 
         sub(/_.*/,"",$1); 
         c[$1]=$2","$4; 
         next 
       } 
    END{ 
       print "col1,col2,col4,col6,col7,col10,col12"; 
       for(i in a){ 
           printf("%s,%s,%s,%s\n",i,a[i],b[i]?b[i]:",",c[i]?c[i]:",") 
          } 
     } 
    '  file1 file2 file3 

在某個時候也會嘗試添加說明。

編輯1:也增加了一種單線形式的解決方案。

awk 'BEGIN{FS=";"}FNR==1{f++} f==1 && FNR>1{;a[$1]=$2","$4;next} f>1 && FNR==1{FS=","} f==2&&FNR>1{sub(/_.*/,"",$1);b[$1]=$2","$3;next} f==3&&FNR>1{sub(/_.*/,"",$1);c[$1]=$2","$4;next} END{print "col1,col2,col4,col6,col7,col10,col12";for(i in a){printf("%s,%s,%s,%s\n",i,a[i],b[i]?b[i]:",",c[i]?c[i]:",")}}' file1 file2 file3 
+0

感謝您的解決方案。它工作正常。有一件事是,結果並沒有像file1那樣保持行的原始順序。我可以在此專欄之後排除課程,但是這種排序也可以包含在'awk'命令中嗎? – user1987607

+0

當file2或3包含比文件1多的行時,我遇到了一個問題。在這種情況下,來自file2或file3的信息不會添加到標準輸出中。當file1包含更多的文件2或3行時,沒有問題。 – user1987607

0

排序 + 的sed招(用於排序的輸入文件):

join -t, -j1 -a1 -o1.1,1.2,1.4,2.2,2.3 <(tr ';' ',' < file1) <(sed 's/_[^,]*//g' file2) 
| join -t, - -a1 -o1.1,1.2,1.3,1.4,1.5,2.2,2.4 <(sed 's/_[^,]*//g' file3) 

輸出:

SAMPLE-1,1,1,2,2,3,3 
SAMPLE-2,1,1,2,2,3,3 
SAMPLE-3,1,1,2,2,3,3 
SAMPLE-4,1,1,,,, 
相關問題