2011-09-01 4 views
1

Je souhaite concaténer deux fichiers ou plus en fonction de la présence ou de l'absence d'éléments dans un tableau.Bash: Cat basé sur la variable de tableau

Je lis ce genre de fichier ligne par ligne (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=() 

Pour chaque ligne, le script extrait la chaîne sur la première colonne et il définit comme la pdbid variable. Ensuite, il prend la deuxième colonne et la définit comme un tableau (chaîne d'éléments $ c). Puis il vérifie si un fichier appelé $ {pdbid} _ $ {c} _p.pdb existe et, si c'est le cas, il fusionne son contenu dans le fichier $ {pdbid} _p _ $ {chaînes} .pdb

Ceci est le script:

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 

le comportement attendu était de fusionner, par exemple, pour la première ligne, et 2PJY_p_B.pdb 2PJY_p_C.pdb dans un fichier appelé 2PJY_p_BC.pdb. Cependant, ce qu'il fait est de fusionner le premier fichier deux fois. Je ne peux pas comprendre pourquoi ...

+1

Utilisez -vx 'set -vx' pour vous aider à déboguer les valeurs de vos variables? Bonne chance. – shellter

Répondre

1

C'est une bonne question, car elle démontre que bash ne peut pas tout faire tout seul. Au lieu de cela, il a besoin d'aides telles que awk, couper, ... J'ai regardé votre solution et il semble qu'après les deux lignes source, vous vous attendez à avoir des variables pdbid, chaîne, et les chaînes définies. Cependant, votre script ne les a pas correctement définis et je peux vous aider avec cette partie. Je ne connais pas tellement Perl, mais je pense que Perl fonctionnera bien dans ce cas. Voici 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"; 
    } 
} 

Et voici le script 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 

J'espère que cela aide.

+0

Merci pour cette solution Perl. Je vais essayer. – mirix

0

Les problèmes semble être la définition du tableau dans cette ligne:

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

Changer à:

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

semble résoudre le problème.

De plus, j'ai double-cité toutes les occurrences de "$ {chain [@]}".

1

Je suggère de prétraiter l'entrée sous une forme plus simple avec sed, puis de boucler dessus. Cela suppose que le chain=(...) est toujours le premier attribut de ce type sur une ligne. Cela évite l'utilisation de fichiers temporaires qui ont criblé votre premier script; le sourcing d'un fichier généré semble également plutôt surprenant, voire alarmant (en général, vous pouvez utiliser des backticks pour ce genre de chose, mais ils ne sont pas vraiment requis ici). Il existe plusieurs variantes de sed; certains (par exemple, Linux) veulent qu'une parenthèse littérale soit masquée par une barre oblique inverse, contrairement à d'autres (par exemple Mac OSX). Si cela ne fonctionne pas, essayez de supprimer les barres obliques inverses.

readread avec plusieurs noms de variables divise l'entrée sur les espaces de sorte que le premier nom de variable reçoive le premier jeton, etc; la dernière variable nommée reçoit ce qui reste, sans division additionnelle des espaces. continue passe à l'itération suivante de la boucle for ou while. Autre que cela, cela devrait être assez explicite. Si vous êtes vraiment pressé de tout faire dans un shell Bourne pur, le remplacement sed au début pourrait probablement être remplacé par quelque chose impliquant des substitutions de chaînes.

Questions connexes