合并多个文件

3
我有多个文件,每个文件中都包含以下内容:
>HM001
ATGCT...
>HM002
ATGTC...
>HM003
ATGCC...

也就是说,每个文件都包含了HM001到HM050物种的一个基因序列。我想把所有这些文件连接起来,生成一个包含HM001到HM050物种基因组的单一文件:

>HM001
ATGCT...ATGAA...ATGTT
>HM002
ATGTC...ATGCT...ATGCT
>HM003
ATGCC...ATGC...ATGAT

最终文件中实际上不需要省略号。我想应该使用cat命令,但我不确定如何使用。如果有任何想法,将不胜感激。

5个回答

3
数据解析和格式化使用awk会更加容易。尝试这样做:
awk -v RS=">" 'FNR>1{a[$1]=a[$1]?a[$1] FS $2:$2}END{for(x in a) print RS x ORS a[x]}' f1 f2 f3

对于像这样的文件:

==> f1 <==
>HM001
ATGCT...
>HM002
ATGTC...
>HM003
ATGCC...

==> f2 <==
>HM001
ATGDD...
>HM002
ATGDD...
>HM003
ATGDD...

==> f3 <==
>HM001
ATGEE...
>HM002
ATGEE...
>HM003
ATGEE...

awk -v RS=">" 'FNR>1{a[$1]=a[$1]?a[$1] FS $2:$2}END{for(x in a) print RS x ORS a[x]}' f1 f2 f3
>HM001
ATGCT... ATGDD... ATGEE...
>HM002
ATGTC... ATGDD... ATGEE...
>HM003
ATGCC... ATGDD... ATGEE...


太好了,谢谢。有没有一种方法可以将位于X文件夹中的所有文件连接起来,而不是编写所有文件名(f1、f2、f3)?我问这个问题是因为X文件夹中有数千个文件。 - user1038055
@user1038055 不用谢。你可以使用 glob。不需要写文件名,只需在给定目录中放置 * 即可引用所有文件。 - jaypal singh

0

我可以建议将您的文件组转换为CSV格式吗?这几乎就是您所建议的,而且很容易集成到任何处理应用程序中(例如Excel、R、Python)。

首先,我假设所有物种和基因序列都只是字母数字,没有空格或类似引号的字符。我还假设可以访问sedsortuniq,它们在*nix、MacOSX中都是标准的,并且可以通过msyscygwin等方式轻松地在Windows上访问。

首先,生成一个文件名和物种的数组。我假设文件名为file1file2等。只需相应地调整第一行即可;它只是一个glob,而不是一个执行的命令。

FILES=($(file*))
SPECIES=($(sed -ne 's/^>//gp' file* | sort | uniq))

这样我们就可以得到每个物种一个排好序的行,没有重复。这能确保我们的列是独立的且集合是完整的。

接下来,请创建一个带有命名列的 CSV 标题行,并将其转储到名为csvfile的 CSV 文件中:

echo -n "\"Species\"" > csvfile
for fn in ${FILES[@]} ; do echo -n ",\"${fn}\"" ; done >> csvfile
echo >> csvfile

现在迭代遍历每个基因序列,并从所有文件中提取它:

for sp in ${SPECIES[@]} ; do
    echo -n "\"${sp}\""
    for fn in ${FILES[@]}; do
        ANS=$(sed -ne '/>'${sp}'/,/^/ { /^[^>]/p }' ${fn})
        echo -n ",\"${ANS}\""
    done
    echo
done >> csvfile

这个方法可以工作,但对于更大的数据集(即大量文件和/或物种)来说效率不高。更好的实现方式(例如Python、Ruby、Perl甚至R)将一次性读取每个文件,形成一个内部维护的矩阵、字典或关联数组,并一次性写出CSV。


0
另一种 awk 实现:
awk '
    {key=$0; getline; value[key] = value[key] $0} 
    END {for (key in value) {print key; print value[key]}}
' file ...

现在,这可能不会按排序顺序输出键:数组键本质上是未排序的。为确保排序输出,请使用gawk和

awk '
    {key=$0; getline; val[key] = val[key] $0} 
    END {
        n = asorti(val, keys)
        for (i=1; i<=n; i++) {print keys[i]; print val[keys[i]]}
    }
' file ...

0

使用echo将它们附加起来怎么样?就像这样:

find . -type f -exec bash -c 'echo "append this" >> "$0"' {} \;

来源:https://dev59.com/qnDXa4cB1Zd3GeqP8BO_#15604608

我会使用"type"来完成,但那是MSDOS的。上面的方法应该适用于你。


{}不应以那种方式使用。想象一个名为lol"; rm -rf . ; "true的文件,哎呀。而是使用:find . -type f -exec bash -c 'echo "append this" >> "$0"' {} \; - gniourf_gniourf
1
@gniourf_gniourf 我早有预料,但我更想引起回声的关注。我的Linux技能为1.5/5(足以在Linux上安装和管理redmine,并且足够老,曾经支持过xenix :))。请继续编辑答案。 - Anthony Horne

0
我能想到最简单的方法是使用cat命令。例如(假设您正在使用*nix类型的系统):
cat file1 file2 file3 > outfile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接