2014-10-09 73 views
0

我试图编写一个脚本,每个文件都需要两列,并将它们水平连接在一起。问题是,列的内容在文件中的顺序不同,所以数据需要在连接之前进行排序。来自多个文件的列的水平合并

这是我想出迄今:

!/bin/bash 

ls *.txt > list 

while read line; do 
    awk '{print $2}' "$line" > f1 
    awk '{print $8}' "$line" > f2 
    paste f1 f2 | sort > "$line".output 
done < list 

ls *.output > list2 

head -n 1 list2 > start 

while read line; do 
    cat "$line" > output 
done < start 

tail -n +2 list2 > list3 

while read line; do 
    paste output "$line" | cat > output 
done < list3 

我的编程是可能不是有效的,但它确实我想要它做的,与倒数第二行以外的东西,这不会将文件连接在一起。如果我在命令行中输入该行,它可以正常工作,但在while循环中会丢失列。

数据文件是这样的:

bundle_id target_id length eff_length tot_counts uniq_counts est_counts eff_counts ambig_distr_alpha ambig_distr_beta fpkm fpkm_conf_low fpkm_conf_high solvable tpm 
1 comp165370_c0_seq1 297 0.000000 0 0 0.000000 0.000000 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 F 0.000000e+00 
2 comp75418_c0_seq1 1371 852.132325 35 0 0.005490 0.008832 8.287807e-04 5.283100e+00 4.583199e-04 0.000000e+00 2.425095e-02 T 6.225299e-04 
3 comp76235_c0_seq1 1371 871.645349 44 9 43.994510 69.198412 2.002884e+00 3.142003e-04 3.590738e+00 3.516301e+00 3.665174e+00 T 4.877251e+00 
4 comp31034_c0_seq1 379 251.335522 14 0 7.049180 10.629771 1.000000e+00 1.000000e+00 1.995307e+00 0.000000e+00 5.957982e+00 F 2.710199e+00 
5 comp36102_c0_seq1 379 234.689179 14 0 6.950820 11.224893 1.000000e+00 1.000000e+00 2.107017e+00 0.000000e+00 6.350761e+00 F 2.861933e+00 
6 comp26522_c0_seq1 220 0.000000 0 0 0.000000 0.000000 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 F 0.000000e+00 
7 comp122428_c0_seq1 624 0.000000 0 0 0.000000 0.000000 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 F 0.000000e+00 

我需要的target_id和eff_counts列。

这不是完整的问题,但我认为我会从小处着手。稍后我希望目标ID仅在开始时出现一次。我想在新文件中有一个标题,其中包含对特定列作出贡献的文件的名称。

target_id    file_1  file_2  file_3 
comp26522_c0_seq1  0.000000  [number]  [number] 
comp31034_c0_seq1  10.629771  [number]  [number] 
comp36102_c0_seq1  11.224893  [number]  [number] 
comp75418_c0_seq1  0.008832  [number]  [number] 
comp76235_c0_seq1  69.198412  [number]  [number] 
comp122428_c0_seq1 0.000000  [number]  [number] 
comp165370_c0_seq1 0.000000  [number]  [number] 

编辑: 我在示例中添加了更多信息。 [号码]只是占位符;实际上,它们将是与file_1下的行类似的数字。此外,头文件“file_1”将是输入文件的名称。 target_id应该排序。所有文件应包含相同的target_id,但所有文件的顺序不同。

编辑二:输出

我有四个文件进行了测试,输出如下:

comp0_c0_seq1 0.000000 
    comp100000_c0_seq1  1.919404 
    comp100002_c0_seq1  2.118776 
    comp100003_c0_seq1  0.072916 
    comp100004_c0_seq1  0.000000 
    comp100005_c0_seq1  0.000000 
    comp100006_c0_seq1  1.548160 
    comp100007_c0_seq1  7.616481 
    comp100008_c0_seq1  0.000000 
    comp100009_c0_seq1  1.374209 

有一个空列与数据第一列的左侧。并且只有来自最后一个文件的数据存在。

谢谢你的帮助!

更新:

我解决了第二行的问题。这是我使用的代码:

while read line; do 
    join output "$line" > output2 
    cat output2 > output 
done < list3 

这是输出:

comp0_c0_seq1  0.000000 0.000000 0.000000 0.000000 
comp100000_c0_seq1 1.919404 1.919404 0.000000 1.919404 
comp100002_c0_seq1 2.118776 2.118776 2.225852 2.118776 
comp100003_c0_seq1 0.072916 0.072916 1.228136 0.072916 
comp100004_c0_seq1 0.000000 0.000000 0.000000 0.000000 
comp100005_c0_seq1 0.000000 0.000000 1.982851 0.000000 
comp100006_c0_seq1 1.548160 1.548160 1.902749 1.548160 
comp100007_c0_seq1 7.616481 7.616481 0.000000 7.616481 
comp100008_c0_seq1 0.000000 0.000000 0.000000 0.000000 
comp100009_c0_seq1 1.374209 1.374209 1.378667 1.374209 

现在我只需要弄清楚如何添加页眉与所有的文件名的文件的顶部。

+0

第二部分不清楚。 '23''0''100'是什么意思? – nu11p01n73R 2014-10-09 09:22:23

+0

这些是eff_counts列中的数字。 最后他们应该四舍五入到一个整数,这是probalby为什么我把这些数字作为一个例子,但在他们是浮动文件。 这是我以为我可以很容易地纠正在R一旦我得到正确的输入文件。 – 2014-10-09 09:39:24

+0

在所需的输出23中,特定target_id的file_1中的eff_counts总数是多少?你能给更多的源数据行来获得更好的图片吗? – Kokkie 2014-10-09 15:08:50

回答

0

你也可以用文件名的集合,感兴趣像下面列开始,并使用喜欢这里的解决方案比调换它:Transpose CSV data with awk (pivot transformation)

find . -name "bundle*.txt" -exec awk 'NR>1 {print FILENAME,$2,$8}' {} \; | sed 's/.\//''/' > superbundle.txt 

说明
- 找到类似名称的所有文件束*。TXT
- 执行一个awk语句其示出了文件名和列2和8(没有报头)
- 用sed从文件名中移除./

现在,我们可以用“superbundle.txt”和转置其使用jaypal提到的解决方案。

$ cat transpose.awk 
{ 
    if(!($1 in filenames)) { filename[++types] = $1 }; filenames[$1]++ 
    if(!($2 in target_ids)) { target_id[++num] = $2 }; target_ids[$2]++ 
    map[$1,$2] = $3 
} 
END { 
    printf "%s\t" ,"target_id"; 
    for(ind=1; ind<=types; ind++) { 
     printf "%s%s", sep, filename[ind]; 
     sep = "\t" 
    } 
    print ""; 
    for(target=1; target<=num; target++) { 
     printf "%s", target_id[target] 
     for(val=1; val<=types; val++) { 
      printf "%s%s", sep, map[filename[val], target_id[target]]; 
     } 
     print "" 
    } 
} 

下面的输出只显示了三个文件,因为我只创建了3个包示例文本文件。

$ awk -f transpose.awk superbundle.txt | column -t 
target_id   bundle.txt bundle2.txt bundle3.txt 
comp165370_c0_seq1 0.000000 1.000000  0.000000 
comp75418_c0_seq1 0.008832 2.008832  1.008832 
comp76235_c0_seq1 69.198412 3.198412  2.198412 
comp31034_c0_seq1 10.629771 4.629771  3.629771 
comp36102_c0_seq1 11.224893 5.224893  4.224893 
comp26522_c0_seq1 0.000000 6.000000  4.000000 
comp122428_c0_seq1 0.000000 7.000000  4.000000 
+0

感谢您的意见。您的解决方案看起来比我的更优雅。目前尚未完成我所需要的工作。 文件名应该进入标题,并且属于每个文件的编号应该水平排列,而不是垂直排列(请参阅我的文章中的倒数第二个代码块)。这可能与查找/ awk? – 2014-10-14 07:06:45

+0

我总是收到一条错误消息,但是会有这样的可能吗?找 。 -name“* txt.output”-exec paste {}>输出 – 2014-10-14 08:14:03

0

经过大量的阅读和测试后,我终于想出了一个完全符合我想要的脚本。

它可能不是最有效的地方使用bash,但它工作得很好。

ls *.xprs > list 

while read line; do 
    echo "parsing $line" 
    awk '{print $2}' "$line" > f1 
    awk '{print $8}' "$line" > f2 
    paste f1 f2 | sort | head -n -1 > "$line".output 
done < list 

ls *.output > list2 

head -n 1 list2 > start 

while read line; do 
    cat "$line" > output 
done < start 

tail -n +2 list2 > list3 

while read line; do 
    join output "$line" > output2 2>/dev/null 
    cat output2 > output 
done < list3 
sed '1i Contig_ID' list2 | awk '{printf("%s ", $0)}' | sed -e '$a\' | sed 's/.xprs.output//g' > list4 

cat list4 output > results.txt 
+0

Hi Roger,我看到它的效果,因为我的解决方案得到了相同的结果。 – Kokkie 2014-10-16 10:20:16

+0

Hi Kokkie, 感谢您添加您的解决方案!我总是渴望学习新的方法。 contig_ids文件之间是否匹配?我遇到的问题是每个文件中行的顺序不同,这就是为什么我使用排序然后连接。 我将不得不仔细检查您的解决方案,看看我能否弄清楚您是如何解决问题的。 – 2014-10-17 00:40:47