Bash:Cat基于数组变量

时间:2011-09-01 14:22:07

标签: arrays bash merge cat

我想连接两个或多个文件,具体取决于名称是否包含数组中的元素。

我正在逐行阅读这种文件(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。然而,它实际上做的是合并第一个文件两次。我不明白为什么......

3 个答案:

答案 0 :(得分:1)

这是一个很好的问题,因为它证明了bash不能单独完成所有事情。相反,它需要帮助程序,如awk,cut,......我查看了你的解决方案,看起来在两个行之后,你希望设置变量pdbid,chain和chain。但是,您的脚本没有正确设置它们,我可以帮助完成该部分。我不太了解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

我希望这会有所帮助。

答案 1 :(得分: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替换可能会被涉及字符串替换的东西替换。

答案 2 :(得分:0)

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

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

将其更改为:

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

似乎可以解决问题。

此外,我已经双重引用了所有“$ {chain [@]}”。