다음과 같은 파일이 있습니다.
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