Estoy intentando extraer el ID de secuencia y el número de grupo que aparecen en diferentes líneas dentro del mismo archivo de texto.
La 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... *
El resultado deseado es el ID de secuencia en una columna y el número de grupo correspondiente en la 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
¿Alguien puede ayudarme con esto?
Respuesta1
Con awk:
awk -F '[. ]*' 'NF == 2 {id = $2; next} {print $3, id}' input-file
- dividimos campos en espacios o puntos con
-F '[. ]*'
- con líneas de dos campos, (las
>Cluster
líneas), guarde el segundo campo como ID y pase a la siguiente línea - con otras líneas, imprima el tercer campo y el ID guardado
Respuesta2
Puedes usar awk
para esto:
awk '/>Cluster/{
c=$2;
next
}{
print substr($3,2,length($3)-4), c
}' file
La primera declaración de bloque captura la ID del clúster. La segunda declaración de bloque (la predeterminada) extrae los datos deseados e imprimelos.
Respuesta3
Aquí hay una alternativa con Ruby como frase ingeniosa:
ruby -ne 'case $_; when /^>Cluster (\d+)/;id = $1;when /, (>\w{4}_\w{5})\.\.\./;puts "#{$1} #{id}";end' input_file
o difundir en varias líneas:
ruby -ne 'case $_
when /^>Cluster (\d+)/
id = $1
when /, (>\w{4}_\w{5})\.\.\./
puts "#{$1} #{id}"
end' input_file
Supongo que sólo es más legible que la awk
versión si conoces Ruby y regexen. Como beneficio adicional, este código podría ser un poco más sólido que simplemente dividir las líneas, porque busca el texto circundante.
Respuesta4
Perla:
$ 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
Explicación
perl -ne
: lea el archivo de entrada línea por línea (-n
) y aplique el script proporcionado por-e
a cada línea.if(/^>.*?(\d+)/){$n=$1;}
: si esta línea comienza con>
, busque el tramo más largo de números al final de la línea y guárdelo como$n
.else{ s/.*(>[^.]+).*/$1 $n/; print
: si la línea no comienza con>
, reemplace todo con el tramo más largo de.
caracteres que no sean caracteres después de>
(>[^.]+
), es decir, el nombre de la secuencia ($1
porque tenemoscapturadola coincidencia de expresiones regulares) y el valor actual de$n
.
O, para un enfoque más extraño:
$ 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 es sólo una forma un poco más engorrosa de hacer la misma idea básica que los distintos awk
enfoques. Lo incluyo para completarlo y para los fanáticos de Perl. Si necesita una explicación, simplemente use las soluciones awk :).