1

名前に配列の要素が含まれているかどうかに応じて、2 つ以上のファイルを連結したいと考えています。

この種のファイルを 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 として定義します。次に、2 番目の列を取り、それを配列 (要素のチェーン $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 という名前のファイルにマージされることが予想されていました。ただし、実際に行うことは、最初のファイルを 2 回マージすることです。なぜだか理解できません...

4

3 に答える 3

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など)は文字通りの括弧をバックスラッシュにしたい場合もあれば、MacOSXなどは必要ない場合もあります。これが機能しない場合は、円記号を削除してみてください。

read複数の変数名を使用すると、空白の入力が分割され、最初の変数名が最初のトークンを受け取るようになります。最後に名前が付けられた変数は、追加の空白を分割せずに、残っているものをすべて受け取ります。 continue囲みforまたはwhileループの次の反復にジャンプします。それ以外は、これはかなり自明のはずです。純粋なBourneシェルですべてを実行する必要がある場合はsed、最初の置換を文字列置換を含むものに置き換えることができます。

于 2011-09-05T10:45:40.800 に答える
1

これは素晴らしい質問です。bash だけではすべてを実行できないことを示しているからです。代わりに、awk、cut などのヘルパーが必要です。ソリューションを調べたところ、2 つのソース行の後に、変数 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";
    }
}

そして、ここにシェルスクリプトがあります:

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 に答える
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 に答える