次のファイルがあります。
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などでこれを行うことができる1行のスクリプトを探しています。
PS。ファイルはタブで区切られ、9つの列で構成されています。列9の値はスペースで区切ります。
私の出力は次のようになります。
chr1 HAVANA exon 12613 12721 . + . ENSG00000223972.5 DDX11L1
chr1 HAVANA exon 13221 14409 . + . ENSG00000223972.5 DDX11L1
答え1
次のawk
スクリプトでは、列9に任意の順序でデータを含めることができると想定しています。
このコードは列を分割し、;
その後にオプションのスペースが続きます。次に、結果要素を繰り返し、その要素をスペースに基づいてキーと値のペアに分割します。キー(スペースの左側にあるもの)が2つの文字列のうちgene_id
の1つである場合、またはgene_name
そのキーの値が記憶されます。列9の解析は、2つの文字列が見つかると終了し、その後列が再作成され、変更された行が印刷されます。
このコードはすべての入力を削除します。いいえ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コード1行。少し短く演奏することもできましたが、かなり明確だと思います。
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