Tengo un archivo (>80.000 líneas) que se parece a este:
chr1 GTF2GFF chromosome 1 249213345 . . . ID=chr1;Name=chr1
chr1 GTF2GFF gene 11874 14408 . + . ID=DDX11L1;Note=unknown;Name=DDX11L1
chr1 GTF2GFF exon 11874 12227 . + . Parent=NR_046018_1
chr1 GTF2GFF exon 12613 12721 . + . Parent=NR_046018_1
chr1 GTF2GFF exon 13221 14408 . + . Parent=NR_046018_1
chr1 GTF2GFF gene 14362 29370 . - . ID=WASH7P;Note=unknown;Name=WASH7P
chr1 GTF2GFF exon 14362 14829 . - . Parent=NR_024540
chr1 GTF2GFF exon 14970 15038 . - . Parent=NR_024540
chr1 GTF2GFF exon 15796 15947 . - . Parent=NR_024540
chr1 GTF2GFF exon 16607 16765 . - . Parent=NR_024540
chr1 GTF2GFF exon 16858 17055 . - . Parent=NR_024540
chr1 GTF2GFF exon 17233 17368 . - . Parent=NR_024540
chr1 GTF2GFF exon 17606 17742 . - . Parent=NR_024540
chr1 GTF2GFF exon 17915 18061 . - . Parent=NR_024540
chr1 GTF2GFF exon 18268 18366 . - . Parent=NR_024540
chr1 GTF2GFF exon 24738 24891 . - . Parent=NR_024540
chr1 GTF2GFF exon 29321 29370 . - . Parent=NR_024540
chr1 GTF2GFF gene 34611 36081 . - . ID=FAM138A;Note=unknown;Name=FAM138A
chr1 GTF2GFF exon 34611 35174 . - . Parent=NR_026818
chr1 GTF2GFF exon 35277 35481 . - . Parent=NR_026818
y quiero extraer solo las filas que contienen "gen" en el tercer campo y reorganizar el noveno campo para que contenga solo el valor de ID (por ejemplo, DDX11L1). Este es el resultado deseado:
chr1 11874 14408 DDX11L1 . +
chr1 14362 29370 WASH7P . -
chr1 34611 36081 FAM138A . -
Usando awk obtuve los campos deseados fácilmente:
head -20 genes.gff3 | awk '$3=="gene" {print $1 "\t" $4 "\t" $5 "\t" $9"\t" $6 "\t" $7}'
chr1 11874 14408 ID=DDX11L1;Note=unknown;Name=DDX11L1 . +
chr1 14362 29370 ID=WASH7P;Note=unknown;Name=WASH7P . -
chr1 34611 36081 ID=FAM138A;Note=unknown;Name=FAM138A . -
Pero tengo dificultades para obtener el valor de identificación. Intenté conectarlo a sed:
head -20 genes.gff3 | awk '$3=="gene" {print $1 "\t" $4 "\t" $5 "\t" $9"\t" $6 "\t" $7}' | sed 's/\(^.+\t\)ID=\(\w+\).+\(\t.+$\)/\1\2\3/g'
y también gsub
head -20 genes.gff3 | awk '$3=="gene" {gsub(/\(^.+\t\)ID=\(\w+\).+\(\t.+$\)/, "\1\2\3", $9); print $1 "\t" $4 "\t" $5 "\t" $9"\t" $6 "\t" $7}'
Pero el resultado es el mismo que si se usara awk solo. ¿Cómo puedo extraer el valor de ID? Siento que estoy muy cerca de una solución aquí.
Salud.
Respuesta1
El separador de campo de la split
función es una expresión regular, por lo que puede dividirlo en =
OR ;
. si sabes eso$9
comienzacon "ID=", entonces
awk -v OFS='\t' '
$3 == "gene" {
split($9, id, /[=;]/)
print $1, $4, $5, id[2], $6, $7
}
' genes.gff3
Si "ID=" no está necesariamente al principio del campo, entonces hay un poco más de trabajo por hacer:
awk -v OFS='\t' '
$3 == "gene" {
id = ""
len = split($9, f, /[=;]/)
for (i=1; i<len; i++) {
if (f[i] == "ID") {
id = f[i+1]
break
}
}
print $1, $4, $5, id, $6, $7
}
' genes.gff3
Respuesta2
Tú podríassplit
el campo y el usosubstr
por:
split($9, a, ";")
print substr(a[1], 4)
Los índices Awk comienzan en 1
.
Otra opción podría ser modificar el separador del campo de entrada ( FS
).
FS
es un espacio, " ", de forma predeterminada, que también tiene el efecto especial deignorando los espacios iniciales y finales.
Además, en lugar de usar print $1, \t, ...
o la printf
variante, se podría configurar OFS
en la pestaña.
Ejemplos:
Modificando FS:
awk -F" +|;|=" '
$3 == "gene" {
printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",
$1, $4, $5, $10, $6, $7);
}
' data.file
Usando división:
awk '
$3 == "gene" {
split($9, a, ";")
printf("%s\t%s\t%s\t%s\t%s\t%s\t\n",
$1, $4, $5, substr(a[1], 3), $6, $7);
}
' data.file
OFS y FS:
Separador de campo de salida( OFS
) como pestaña y alternativa FS
dentro de awk. También actualizado FS
para incluir la pestaña:
awk '
BEGIN {
FS="[ \t]+|;|="
OFS="\t"
}
$3 == "gene" {
print $1, $4, $5, $10, $6, $7
}
' data.file
Ver tambiénEl grupo abierto Variables y variables especiales,Ejemplos.
manual de mirada boquiabierta– Por lo general, se nota cuando las cosas son una extensión de awk.
Respuesta3
Esta es una solución Bash, ya que me permitió publicar, a pesar de la solicitud explícita que solicitaba usar awk
y sed
:
show_genes()
{
local filename="$1"
while read -ra larr; do
if [[ ${larr[2]} = gene ]]; then
larr[8]="${larr[8]%%;*}"
larr[8]="${larr[8]#ID=}"
printf '%s\n' "${larr[*]}"
fi
done < "$filename"
}
Uso:show_genes /ruta/a/algunos/archivo.txt
Salida de muestra:
[rany$] cat data.txt
romosome 1 249213345 . . . ID=chr1;Name=chr1
chr1 GTF2GFF gene 11874 14408 . + . ID=DDX11L1;Note=unknown;Name=DDX11L1
chr1 GTF2GFF exon 11874 12227 . + . Parent=NR_046018_1
chr1 GTF2GFF exon 12613 12721 . + . Parent=NR_046018_1
chr1 GTF2GFF exon 13221 14408 . + . Parent=NR_046018_1
chr1 GTF2GFF gene 14362 29370 . - . ID=WASH7P;Note=unknown;Name=WASH7P
chr1 GTF2GFF exon 14362 14829 . - . Parent=NR_024540
chr1 GTF2GFF exon 14970 15038 . - . Parent=NR_024540
chr1 GTF2GFF exon 15796 15947 . - . Parent=NR_024540
chr1 GTF2GFF exon 16607 16765 . - . Parent=NR_024540
chr1 GTF2GFF exon 16858 17055 . - . Parent=NR_024540
chr1 GTF2GFF exon 17233 17368 . - . Parent=NR_024540
chr1 GTF2GFF exon 17606 17742 . - . Parent=NR_024540
chr1 GTF2GFF exon 17915 18061 . - . Parent=NR_024540
chr1 GTF2GFF exon 18268 18366 . - . Parent=NR_024540
chr1 GTF2GFF exon 24738 24891 . - . Parent=NR_024540
chr1 GTF2GFF exon 29321 29370 . - . Parent=NR_024540
chr1 GTF2GFF gene 34611 36081 . - . ID=FAM138A;Note=unknown;Name=FAM138A
chr1 GTF2GFF exon 34611 35174 . - . Parent=NR_026818
chr1 GTF2GFF exon 35277 35481 . - . Parent=NR_026818
[rany$] show_genes data.txt
chr1 GTF2GFF gene 11874 14408 . + . DDX11L1
chr1 GTF2GFF gene 14362 29370 . - . WASH7P
chr1 GTF2GFF gene 34611 36081 . - . FAM138A
[rany$]
Respuesta4
Sólo una respuesta rápida para la pausa para el café.
perl -ne 's/\t.*?\tgene// #remove \t F2 \t gene
and s/\S*\tID=(.*?);.*/$1/ #remove \t Fn \t ID=.... keeping the id
and print' file