extrair informação de uma coluna [fechada]

0

Eu tenho um arquivo que se parece com isso:

chr1    HAVANA  exon    12613   12721   .   +   .   gene_id "ENSG00000223972.5"; transcript_id "ENST00000456328.2"; gene_type "transcribed_unprocessed_pseudogene"; gene_name "DDX11L1"; transcript_type "processed_transcript"; transcript_name "DDX11L1-202"; exon_number 2; exon_id "ENSE00003582793.1"; level 2; transcript_support_level "1"; tag "basic"; havana_gene "OTTHUMG00000000961.2"; havana_transcript "OTTHUMT00000362751.1";
chr1    HAVANA  exon    13221   14409   .   +   .   gene_id "ENSG00000223972.5"; transcript_id "ENST00000456328.2"; gene_type "transcribed_unprocessed_pseudogene"; gene_name "DDX11L1"; transcript_type "processed_transcript"; transcript_name "DDX11L1-202"; exon_number 3; exon_id "ENSE00002312635.1"; level 2; transcript_support_level "1"; tag "basic"; havana_gene "OTTHUMG00000000961.2"; havana_transcript "OTTHUMT00000362751.1";

Eu quero extrair valores de gene_id e gene_name juntamente com as primeiras 8 colunas (o arquivo é separado por tabulações). Eu escrevi um script em perl que pode fazer isso, mas estou procurando por um forro no awk, sed etc que possa fazer isso.

PS. O arquivo é separado por tabulação e tem 9 colunas. A 9ª coluna tem valores separados por espaços.

Minha saída deve ficar assim:

chr1    HAVANA  exon    12613   12721   .   +   .   ENSG00000223972.5   DDX11L1
chr1    HAVANA  exon    13221   14409   .   +   .   ENSG00000223972.5   DDX11L1
    
por user3138373 11.09.2018 / 00:11

3 respostas

1

Perl one-liner. Pode ser um pouco mais curto, mas acho que isso é bem claro.

perl -F'\t' -lane '
    if (($id, $name) = / \b gene_id \s+ " ([^"]+) .+ \b gene_name \s+ " ([^"]+)/x) {
        print join "\t", @F[0..7], $id, $name;
    }
' file

Um pouco mais "inteligente":

perl -F'\t' -E '$,="\t"; say @F[0..7], $g{id}, $g{name} if %g = /\bgene_(id|name)\s+"([^"]+)/g' file
    
por 11.09.2018 / 00:56
1

awk '{ print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8 "\t" $10 "\t" $16 ; } ' filename > output

sem aspas e ponto e vírgula:

awk '{ print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8 "\t" $10 "\t" $16 ; }' filename | sed -e 's/;//g; s/\"//g;' > output

mais preciso usando apenas o awk:

awk '{ ORS=" "; print $1 "\t" $2 "\t" $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7 "\t" $8 "\t"; gsub(";", "", $10); gsub("\"", "", $10); print $10 "\t"; gsub(";", "", $16) ; gsub("\"", "", $16); print $16 ; ORS="\n" ; print " "; } ' filename > output

    
por 11.09.2018 / 02:43
1

O script awk a seguir supõe que a 9ª coluna pode ter dados em qualquer ordem.

O código dividirá a coluna em ; seguido por um espaço opcional. Em seguida, iterará os elementos resultantes e os dividirá em espaços em um par de valores-chave. Se a chave (a coisa à esquerda do espaço) for qualquer uma das duas cadeias gene_id ou gene_name , o valor dessa chave será lembrado. A análise da 9ª coluna termina quando encontramos nossas duas strings, após as quais a coluna é reescrita e a linha modificada é impressa.

O código também descarta qualquer entrada que não contenha gene_id e gene_name .

BEGIN {
    FS = OFS = "\t"
}

{
    n = split($9, a, "; ?")

    found = 0;
    for (i = 1; i <= n; ++i)
        if (split(a[i], b, " ") == 2) {
            if (b[1] == "gene_id") {
                gene_id = b[2]
                ++found
            } else if (b[1] == "gene_name") {
                gene_name = b[2]
                ++found
            }

            if (found == 2) break
        }

    if (found == 2) {
        $9 = gene_id " " gene_name
        print
    }
}

Teste nos dados fornecidos:

$ awk -f script.awk <file
chr1    HAVANA  exon    12613   12721   .       +       .       "ENSG00000223972.5" "DDX11L1"
chr1    HAVANA  exon    13221   14409   .       +       .       "ENSG00000223972.5" "DDX11L1"

Para remover as aspas duplas dos valores, altere

if (found == 2) {
    $9 = gene_id " " gene_name
    print
}

em

if (found == 2) {
    gsub("\"", "", gene_id)
    gsub("\"", "", gene_name)
    $9 = gene_id " " gene_name
    print
}

que remove todas as aspas duplas do nome do gene e ID, ou

if (found == 2) {
    gene_id = substr(gene_id, 2, length(gene_id) - 2)
    gene_name = substr(gene_name, 2, length(gene_name) - 2)
    $9 = gene_id " " gene_name
    print
}

que remove o primeiro e o último caractere dos dois valores.

    
por 12.09.2018 / 15:52