열에서 정보 추출 [닫기]

열에서 정보 추출 [닫기]

다음과 같은 파일이 있습니다.

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";

gene_id, gene_name 값과 처음 8개 열(파일은 탭으로 구분되어 있음)을 추출하고 싶습니다. 저는 이 작업을 수행하는 스크립트를 Perl로 작성했지만 awk, sed 등에서 이 작업을 수행할 수 있는 한 줄짜리 스크립트를 찾고 있습니다.

추신. 파일은 탭으로 구분되며 9개의 열로 구성됩니다. 9열의 값은 공백으로 구분됩니다.

내 출력은 다음과 같아야 합니다.

chr1    HAVANA  exon    12613   12721   .   +   .   ENSG00000223972.5   DDX11L1
chr1    HAVANA  exon    13221   14409   .   +   .   ENSG00000223972.5   DDX11L1

답변1

다음 awk스크립트에서는 열 9에 어떤 순서로든 데이터가 포함될 수 있다고 가정합니다.

이 코드는 열을 분할하고 ;그 뒤에 선택적 공백이 옵니다. 그런 다음 결과 요소를 반복하고 해당 요소를 공백을 기준으로 키-값 쌍으로 분할합니다. 키(공백 왼쪽에 있는 것)가 두 문자열 gene_id중 하나이거나 이면 gene_name해당 키의 값이 기억됩니다. 열 9의 구문 분석은 두 개의 문자열을 찾으면 종료되며, 그 후에 열이 다시 작성되고 수정된 행이 인쇄됩니다.

이 코드는 또한 모든 입력을 삭제합니다.아니요gene_id및 을 포함합니다 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
    }
}

제공된 데이터를 테스트합니다.

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

값에서 큰따옴표를 제거하려면 다음을 변경하십시오.

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

입력하다

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

이렇게 하면 유전자 이름과 ID의 모든 큰따옴표가 제거됩니다.

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
}

두 값 모두에서 첫 번째 문자와 마지막 문자를 제거합니다.

답변2

Perl 코드 한 줄. 조금 더 짧게 연주할 수도 있었지만 꽤 명확하다고 생각합니다.

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

좀 더 "스마트"하게:

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

답변3

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

따옴표와 세미콜론 없이:

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

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

관련 정보