如何使用 paste/join 或 linux 或 perl 以有序方式有效地加入 'n' 个文件?

How to join 'n' number of files in ordered way efficiently using paste/join or linux or perl?

数以千计的文件以 *.tab 结尾。每个文件的第一列是 header。每个文件都有自己的 header(所以它们是不同的)。我不介意从任何文件中得到一个 header。

所有文件的行数都相等,因此有一个顺序。我想要的输出具有相同的顺序。

目录中的示例文件

test_1.tab
test_2.tab
.
.
.
.
test_1990.tab
test_2000.tab

test_1.tab

Pro_01 0 0 0 0 0 1 1 1 0 1 1 0 .....0
Pro_02 0 0 0 0 0 1 1 0 0 0 0 0 .....1
Pro_03 1 1 1 1 1 0 0 1 0 1 1 0 .....1
.
.
.
Pro_200 0 0 0 0 1 1 1 1 1 1 0  .....0

test_2000.tab

Pro_1901 1 1 1 1 0 1 1 0 0 0 0 1 .....0
Pro_1902 1 1 1 0 0 0 1 0 0 0 0 0 .....1
Pro_1903 1 1 0 1 0 1 0 0 0 0 0 1 .....1
.
.
.
Pro_2000 1 0 0 0 0 1 1 1 1 1 0  .....0

期望的输出

Pro_01 0 0 0 0 0 1 1 1 0 1 1 0 0 ..... 1 1 1 1 0 1 1 0 0 0 0 1 0
Pro_02 0 0 0 0 0 1 1 0 0 0 0 0 1 ..... 1 1 1 0 0 0 1 0 0 0 0 0 1
Pro_03 1 1 1 1 1 0 0 1 0 1 1 0 1 ..... 1 1 0 1 0 1 0 0 0 0 0 1 1
.
.
.
Pro_200 0 0 0 0 1 1 1 1 1 1 0 0  ..... 1 0 0 0 0 1 1 1 1 1 0 0

我的代码

for i in *.tab/; do paste allCol.tab <(cut -f 2- "$i") > itermediate.csv; mv intermediate.csv allCol.tab ; done

paste <(cut -f1 test1.tab) allCol.tab > final.tab
rm allCol.tab

大约需要 3 个小时。哪种方法更好? 另外,是否有任何其他命令可以交叉检查此输出文件与所有输入文件?喜欢 diff 还是 wc?

试试这个。

#!/bin/bash    

TMP=tmp
mkdir "$TMP"
RESULT=result

#read each file and append the contents of each line in them
#to a new file for each line in the tmp directory 
for f in *.tab; do
    i=1
    while read -r l; do
        echo "$l" >> "$TMP"/"$i"
        ((i++))
    done < <(cut -f2- "$f")
done

#integrate each file in tmp dir into a single line of the $RESULT file
exec 1>>$RESULT    
for f in "$TMP"/*; do
    while read -r l; do
        printf '%s\t' "$l"
    done < <(cat "$f")
    echo
done

rm -r "$TMP"

这个算法可以在多个处理器上拆分,任务完成得更快。

您还可以向其中添加诸如检查 $TMP 是否已成功创建之类的内容。

递归函数是一个很好的工具。作为第一次剪辑——简短但简单:

pasteAll() {
  first=; shift
  case $# in
    0) cut -f 2- "$first" ;;
    *) paste <(cut -f 2- "$first") <(pasteAll "$@") ;;
  esac
}

set -- *.tab    
paste <(cut -f 1 "") <(pasteAll "$@")

检查是否包含所有文件和行——如果每个输入文件包含相同数量的行——就像检查输出文件的行数和最后一行的列数一样简单。