J'essaie d'extraire l'ID de séquence et le numéro de cluster qui apparaissent sur différentes lignes dans le même fichier texte.
L'entrée ressemble à
>Cluster 72
0 319aa, >O311_01007... *
>Cluster 73
0 318aa, >1494_00753... *
1 318aa, >1621_00002... at 99.69%
2 318aa, >1622_00575... at 99.37%
3 318aa, >1633_00422... at 99.37%
4 318aa, >O136_00307... at 99.69%
>Cluster 74
0 318aa, >O139_01028... *
1 318aa, >O142_00961... at 99.69%
>Cluster 75
0 318aa, >O300_00856... *
La sortie souhaitée est l’ID de séquence dans une colonne et le numéro de cluster correspondant dans la seconde.
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75
Quelqu'un peut-il aider avec ça?
Avec awk:
awk -F '[. ]*' 'NF == 2 {id = $2; next} {print $3, id}' input-file
-F '[. ]*'
>Cluster
), enregistrez le deuxième champ comme ID et passez à la ligne suivanteVous pouvez utiliser awk
pour cela:
awk '/>Cluster/{
c=$2;
next
}{
print substr($3,2,length($3)-4), c
}' file
La première instruction de bloc est la capture de l'ID de cluster. La deuxième instruction de bloc (celle par défaut) extrait les données souhaitées et les affiche.
Voici une alternative avec Ruby comme une ligne:
Ruby -ne 'case $_; when /^>Cluster (\d+)/;id = $1;when /, (>\w{4}_\w{5})\.\.\./;puts "#{$1} #{id}";end' input_file
ou répartis sur plusieurs lignes:
Ruby -ne 'case $_
when /^>Cluster (\d+)/
id = $1
when /, (>\w{4}_\w{5})\.\.\./
puts "#{$1} #{id}"
end' input_file
Je suppose que c'est seulement plus lisible que la version awk
si vous connaissez Ruby et regexen. En prime, ce code pourrait être un peu plus robuste que le simple découpage des lignes, car il recherche le texte environnant.
Perl:
$ Perl -ne 'if(/^>.*?(\d+)/){$n=$1;}else{ s/.*(>[^.]+).*/$1 $n/; print}' file
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75
Perl -ne
: lit le fichier d'entrée ligne par ligne (-n
) et applique le script donné par -e
à chaque ligne.if(/^>.*?(\d+)/){$n=$1;}
: si cette ligne commence par un >
, trouvez le plus long tronçon de nombres à la fin de la ligne et enregistrez-le sous le nom $n
.else{ s/.*(>[^.]+).*/$1 $n/; print
: si la ligne ne commence pas par >
, remplacez le tout par le plus long tronçon de caractères non -.
après un >
(>[^.]+
), c’est-à-dire le nom de la séquence. ($1
parce que nous avons capturé la correspondance d'expression régulière) et la valeur actuelle de $n
.Ou, pour une approche plus proche de la awk:
$ Perl -lane 'if($#F==1){$n=$F[1]}else{$F[2]=~s/\.+$//; print "$F[2] $n"}' file
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75
C’est une façon un peu plus lourde de faire la même idée de base que les différentes approches awk
. Je l’inclus pour des raisons d’achèvement et pour les fans de Perl. Si vous avez besoin d'explications, utilisez simplement les solutions awk :).