Estou tentando extrair o ID de sequência e o número do cluster que ocorrem em linhas diferentes no mesmo arquivo de texto.
A entrada parece
>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... *
A saída desejada é o ID de sequência em uma coluna e o número do cluster correspondente na segunda.
>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
Alguém pode ajudar com isso?
Responder1
Com awk:
awk -F '[. ]*' 'NF == 2 {id = $2; next} {print $3, id}' input-file
- dividimos os campos em espaços ou períodos com
-F '[. ]*'
- com linhas de dois campos, (as
>Cluster
linhas), salve o segundo campo como o ID e passe para a próxima linha - com outras linhas, imprima o terceiro campo e o ID salvo
Responder2
Você pode usar awk
para isso:
awk '/>Cluster/{
c=$2;
next
}{
print substr($3,2,length($3)-4), c
}' file
A primeira instrução de bloco captura o ID do cluster. A segunda instrução de bloco (a padrão) está extraindo os dados desejados e imprimindo-os.
Responder3
Aqui está uma alternativa com Ruby como one-liner:
ruby -ne 'case $_; when /^>Cluster (\d+)/;id = $1;when /, (>\w{4}_\w{5})\.\.\./;puts "#{$1} #{id}";end' input_file
ou espalhado em várias linhas:
ruby -ne 'case $_
when /^>Cluster (\d+)/
id = $1
when /, (>\w{4}_\w{5})\.\.\./
puts "#{$1} #{id}"
end' input_file
Acho que só é mais legível que a awk
versão se você conhece Ruby e regexen. Como bônus, esse código pode ser um pouco mais robusto do que simplesmente dividir as linhas, porque procura o texto ao redor.
Responder4
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
Explicação
perl -ne
: leia o arquivo de entrada linha por linha (-n
) e aplique o script fornecido por-e
a cada linha.if(/^>.*?(\d+)/){$n=$1;}
: se esta linha começar com>
, encontre o trecho mais longo de números no final da linha e salve-o como$n
.else{ s/.*(>[^.]+).*/$1 $n/; print
: se a linha não começar com>
, substitua tudo pelo trecho mais longo de não-.
caracteres após um>
(>[^.]+
), ou seja, o nome da sequência ($1
porque temoscapturadoa correspondência de regex) e o valor atual de$n
.
Ou, para uma abordagem mais estranha:
$ 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
Esta é apenas uma maneira um pouco mais complicada de executar a mesma ideia básica das várias awk
abordagens. Estou incluindo-o para fins de conclusão e para os fãs de Perl. Se precisar de uma explicação, basta usar as soluções awk :).