1

我想根据名称是否包含数组中的元素来连接两个或多个文件。

我正在逐行读取这种文件(proteome.pisa):

2PJY_p  chain=(B C) hresname=() hresnumber=()   hatom=()    model=()    altconf=()
2Q7N_p  chain=(A E F G H I J K L)   hresname=(FUC MAN NAG)  hresnumber=()   hatom=()    model=()    altconf=()

对于每一行,脚本提取第一列的字符串并将其定义为变量 pdbid。然后它获取第二列并将其定义为一个数组(元素链 $c)。然后它检查是否存在名为 ${pdbid}_${c}_p.pdb 的文件,如果存在,它将其内容合并到文件 ${pdbid}_p_${chains}.pdb

这是脚本:

while read line ; do

echo "$line" > pdb.line
cut -f1 pdb.line > pdb.list
sed -i 's/.*/\"&\"/' pdb.list
sed -i 's/_p//g' pdb.list
awk '{ printf "pdbid="; print }' pdb.list > pdbid.list

cut -f2 pdb.line > chain.list

source pdbid.list
source chain.list

chains=`printf "%s" "${chain[@]}"`

for c in ${chain[@]} ; do
if [ ${#chain[@]} -gt 1 ] && \
   [ -f ${pdbid}_${c}_p.pdb ] ; then  
cat ${pdbid}_${chain[$c]}_p.pdb >> ${pdbid}_p_${chains}.pdb
fi
done

done < proteome.pisa

例如,预期的行为是将第一行的 2PJY_p_B.pdb 和 2PJY_p_C.pdb 合并到一个名为 2PJY_p_BC.pdb 的文件中。但是,它实际上所做的是将第一个文件合并两次。我无法理解为什么...

4

3 回答 3

1

这是一个很好的问题,因为它表明 bash 不能独自完成所有事情。相反,它需要诸如 awk、cut 之类的帮助程序……我查看了您的解决方案,似乎在两条源代码行之后,您希望设置变量 pdbid、chain 和chains。但是,您的脚本没有正确设置它们,我可以在这部分提供帮助。我不太了解 Perl,但认为 Perl 在这种情况下会很好地工作。这是makevars.pl

while (<STDIN>) {
    my($line) = $_;
    if ($line =~ /^(.*)_p.*chain=\((.*)\).*hresname.*$/) {
        print "pdbid=$1\n";
        print "chain=($2)\n";
        $chains = $2;
        $chains =~ s/ //g;
        print "chains=$chains\n";
    }
}

这是shell脚本:

while read line
do

    echo "$line" | perl makevars.pl >setvars.sh
    source setvars.sh
    # Now, pdbid, chain, and chains are set, do your things

done < proteome.pisa

我希望这有帮助。

于 2011-09-01T20:06:26.367 回答
1

我建议使用 将输入预处理为更简单的形式sed,然后对其进行循环。这是假设chain=(...)始终是一行中的第一个此类属性。

#!/bin/sh

# Replace 2ICQ_p chain=(A B C ... Z) attribs= ...   with
# 2ICQ_p A B C ... Z
sed 's/ chain=\(//;s/\).*//' <proteome.pisa |
while read pdbid chain; do
    chains=${chain/ /}
    for c in $chain; do
        test -e ${pdbid}_${c}_p.pdb || continue
        cat ${pdbdid}_${c}_p.pdb
    done >${pdbid}_p_${chains}.pdb
done

这样可以避免使用使您的第一个脚本百思不得其解的临时文件;采购一个生成的文件看起来也相当惊人,如果不是令人震惊的话(通常你可以使用反引号来处理这类事情,但这里并不需要它们)。

有多种变体sed;有些人(例如Linux)希望文字括号被反斜杠,其他人(例如Mac OSX)不希望。如果这不起作用,请尝试删除反斜杠。

read使用多个变量名将输入拆分为空格,以便第一个变量名接收第一个标记等;最后一个命名的变量接收剩下的任何东西,而不需要额外的空格分割。 continue跳转到封闭forwhile循环的下一次迭代。除此之外,这应该是不言自明的。如果你真的被迫在纯 Bourne shell 中完成这一切,sed那么开头的替换可能会被替换为涉及字符串替换的东西。

于 2011-09-05T10:45:40.800 回答
0

问题似乎是这一行中数组的定义:

cat ${pdbid}_${chain[$c]}_p.pdb >> ${pdbid}_p_${chains}.pdb

将其更改为:

cat ${pdbid}_${c}_p.pdb >> ${pdbid}_p_${chains}.pdb

似乎可以解决问题。

此外,我双引号引用了所有出现的“${chain[@]}”。

于 2011-09-02T05:58:04.947 回答