
¿Existe una forma eficaz de analizar un archivo como:
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
a:
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
El patrón es siempre |||
; - luego comienza CSQ
y termina con el quinto campo - sin embargo ese campo no siempre es missense variant
pero también puede ser algo diferente como kdjdud
.
Hay muchas líneas (más de 60k) en el archivo y necesitaría extraer esta tabla de pestañas como se muestra arriba. ¿Existe una solución Python, Perl o AWK (u otra cosa) para eso?
Respuesta1
Usemos sed
:
sed -r 's/.*\|\|\|;(CSQ[^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|.*/\1\t\2\t\3\t\4\t\5/' file.txt
python
no es rápido para manipular archivos muy grandes, esto sería mucho más rápido que python
.
Ejemplo:
% cat file.txt
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
% sed -r 's/.*\|\|\|;(CSQ[^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|.*/\1\t\2\t\3\t\4\t\5/' file.txt
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
Respuesta2
Usando Perl:
perl -F'\|\|\|' -lane '$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)' file
-F'\|\|\|'
: establece el separador de campo de entrada en|||
;-l
: habilita el procesamiento automático de fin de línea. Tiene dos efectos separados. Primero, corta automáticamente $/ (el separador de registros de entrada) cuando se usa con -n o -p. En segundo lugar, asigna $\ (el separador de registros de salida) para que tenga el valor de octnum, de modo que a cualquier declaración impresa se le vuelva a agregar ese separador. Si se omite octnum, establece $\ en el valor actual de $/.-a
: activa el modo de división automática cuando se usa con -n o -p. Un comando de división implícito para la matriz @F se realiza como lo primero dentro del bucle while implícito producido por -n o -p.n
: hace que Perl asuma el siguiente bucle alrededor de su programa, lo que hace que itere sobre los argumentos del nombre de archivo algo así como sed -n o awk:LINE: while (<>) { ... # your program goes here }
-e
: puede usarse para ingresar una línea de programa.$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)
: establece el separador de campos de salida en\t
, divide el segundo campo de la línea actual en;
o|
, elimina el primer campo vacío e imprime los campos restantes.
% cat file
2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
% perl -F'\|\|\|' -lane '$, = "\t"; @f = split(/;|\|/, $F[1]); shift(@f); splice(@f, 5); print(@f)' file
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
%
Respuesta3
Esto debería funcionar para ti:
cut -d"|" -f4,5,6,7,8 filename.txt | sed 's/;//g' | sed 's/|/\t/g'
Ejemplo:
$ echo "2 41620 . T G 100 PASS AC=3;AF=0.000599042;AN=5008;NS=2504;DP=18872;EAS_AF=0;AMR_AF=0;AFR_AF=0;EUR_AF=0;SAS_AF=0.0031;AA=.|||;CSQ=G|ENSG00000184731|ENST00000327669|Transcript|missense_variant|954|954|318|K/N|aaA/aaC|||-1|tolerated(0.47)|benign(0)||||;GENCODE=ENST00000327669
" | cut -d"|" -f4,5,6,7,8 | sed 's/;//g' | sed 's/|/\t/g'
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
Explicación
cut -d"|" -f4,5,6,7,8 filename.txt #-> split the line at | and return fields 4 to 8
| sed 's/;//g' #-> remove the ;
| sed 's/|/\t/g' #-> replace | with tab
Respuesta4
solución pitón
#!/usr/bin/env python
import re,sys
with open(sys.argv[1]) as fd:
for line in fd:
pattern=[ x for x in re.split('\|\|\||;',line)
if 'CSQ' in x]
if pattern:
print(" ".join(pattern[0].split("|")[0:5]))
PRUEBA
Con la línea original de OP pegada 3 veces y ligeramente editada eninput.txt
$ ./extract_pattern.py input.txt
CSQ=G ENSG00000184731 ENST00000327669 Transcript missense_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript random_variant
CSQ=G ENSG00000184731 ENST00000327669 Transcript other_variant
Explicación
El script abre el archivo proporcionado en la línea de comandos como argumento ( sys.argv[1]
) y lee el archivo línea por línea. Primero usamos re.split()
la función para dividir cada línea en múltiples delimitadores: 3 barras verticales o ;
, lo que permite que los datos relevantes estén contenidos dentro de una cadena. Luego encontramos esa cadena (que contiene CSQ
). Si lo encontramos, la cadena se divide nuevamente en una lista de cadenas, ahora solo usando .split()
la función que usa la barra vertical como delimitador. La lista resultante se divide para tomar los primeros 5 elementos (la [0:5]
parte) y se vuelve a unir en una nueva cadena usando el espacio como delimitador.