特定の列から引用符とタグ付きデータを抽出します。

特定の列から引用符とタグ付きデータを抽出します。

私は大きなものを持っていますGTFファイル、次のように:

 # ./stringtie -p 4 -G /home/humangenome_hg19/homo_gtf_file.gtf -o strAD1_as/transcripts.gtf -l strAD1 /home/software/star-2.5.2b/bin/Linux_x86_64/mapA1Aligned.sortedByCoord.out.bam                               
# StringTie version 1.3.2d                              
1   StringTie   transcript  30267   31109   1000    +   .   gene_id "strAD1.1"; transcript_id "strAD1.1.1"; reference_id "ENST00000469289"; ref_gene_id "ENSG00000243485"; ref_gene_name "MIR1302-10"; cov "0.028725"; FPKM "0.053510"; TPM "0.109957";
1   StringTie   exon    30267   30667   1000    +   .   gene_id "strAD1.1"; transcript_id "strAD1.1.1"; exon_number "1"; reference_id "ENST00000469289"; ref_gene_id "ENSG00000243485"; ref_gene_name "MIR1302-10"; cov "0.014218";
1   StringTie   exon    30976   31109   1000    +   .   gene_id "strAD1.1"; transcript_id "strAD1.1.1"; exon_number "2"; reference_id "ENST00000469289"; ref_gene_id "ENSG00000243485"; ref_gene_name "MIR1302-10"; cov "0.072139";

gene_id9列には、およびtranscript_idのみreference_id含めたいと思いますref_gene_id。列9にあり、スペースで区切られています(列自体はタブで区切られています)。簡単なコマンドを使用してLinuxでこれらの列を作成する方法を教えてください。私はExcelを使用したくありません。

答え1

理想的には、データはGTF形式であるため、GTFパーサーを使用して解析する必要があります。現在、このようなパーサーや解析ライブラリはインストールされていないため、私のソリューションはあなたが質問に提供したデータのみに基づいています。

列 9 を抽出するには、次のようにします。

$ cut -f 9 data.gtf
gene_id "strAD1.1"; transcript_id "strAD1.1.1"; reference_id "ENST00000469289"; ref_gene_id "ENSG00000243485"; ref_gene_name "MIR1302-10"; cov "0.028725"; FPKM "0.053510"; TPM "0.109957";
gene_id "strAD1.1"; transcript_id "strAD1.1.1"; exon_number "1"; reference_id "ENST00000469289"; ref_gene_id "ENSG00000243485"; ref_gene_name "MIR1302-10"; cov "0.014218";
gene_id "strAD1.1"; transcript_id "strAD1.1.1"; exon_number "2"; reference_id "ENST00000469289"; ref_gene_id "ENSG00000243485"; ref_gene_name "MIR1302-10"; cov "0.072139";

ここで目的のデータを取得するには、転写物とエクソンの属性がデータ内で異なる順序になっているため、別々に処理する必要があります。これを行いawk、現在の行に文字列が含まれているかどうかによって入力データとは異なるフィールドを出力しますexon_number

$ cut -f 9 data.gtf | awk '/exon_number/ { print $2, $4, $8, $10; next } { print $2, $4, $6, $8 }'
"strAD1.1"; "strAD1.1.1"; "ENST00000469289"; "ENSG00000243485";
"strAD1.1"; "strAD1.1.1"; "ENST00000469289"; "ENSG00000243485";
"strAD1.1"; "strAD1.1.1"; "ENST00000469289"; "ENSG00000243485";

次に二重引用符とセミコロンを削除します。

$ cut -f 9 data.gtf | awk '/exon_number/ { print $2, $4, $8, $10; next } { print $2, $4, $6, $8 }' | tr -d '";'
strAD1.1 strAD1.1.1 ENST00000469289 ENSG00000243485
strAD1.1 strAD1.1.1 ENST00000469289 ENSG00000243485
strAD1.1 strAD1.1.1 ENST00000469289 ENSG00000243485

答え2

たぶんただ:

< file cut -sd '"' -f2,4,8,10 | tr '"' ' '

つまり、入力を別々"列のリストとして処理し、列2、4、8、および10抽出します。

GNUを使用するcutと。| tr '"' ' '--output-delimiter=' '

これは"、文字が行の他の場所には表示されず、対応する、gene_id...transcript_id属性が常にその順序で表示され、常に表示されると仮定します。

Kusalanandaが指摘したように、あなたの例ではそうではありません。2,4,6,8最初の行と2,4,8,10他の行は次のようにする必要があります。

より表現力のある一致を作成するには、タブで区切られた9番目の列のみを考慮して正しい属性名を見つける必要があります。正規表現を使用できます。たとえば、次のようになります。

< file pcregrep -o1 -o2 -o3 -o4 --om-separator=' ' '(?x)
  ^(?:[^\t]*+\t){8}(?=[^\t]*? \b gene_id       \ +"([^"\t]*)")
                   (?=[^\t]*? \b transcript_id \ +"([^"\t]*)")
                   (?=[^\t]*? \b reference_id  \ +"([^"\t]*)")
                   (?=[^\t]*? \b ref_gene_id   \ +"([^"\t]*)")'

そのバージョンがないpcregrep場合、またはバージョンが古すぎてサポートできない場合は、-o1...次のものを使用できますperl

< file perl -lne 'print "$1 $2 $3 $4" if m{
  ^(?:[^\t]*+\t){8}(?=[^\t]*? \b gene_id       \ +"([^"\t]*)")
                   (?=[^\t]*? \b transcript_id \ +"([^"\t]*)")
                   (?=[^\t]*? \b reference_id  \ +"([^"\t]*)")
                   (?=[^\t]*? \b ref_gene_id   \ +"([^"\t]*)")}x'

この正規表現は最初に最初の8つのフィールド((?:[^\t]*+\t){8})と一致し、次に4つの予測式()があるため、次の内容が(?=...)4つの予測式とすべて一致する場合は、8つのフィールドを一致させます。各予測式は属性の1つを見つけて値をキャプチャします(ウィジェットで(...))。このようにキャプチャされた値は、、、、$1$2使用$3できます$4

これにより、属性を任意の順序で並べ替えることができます。

次の方法でだますことができます。

1 2 3 4 5 6 7 8 gene_id "transcript_id " ...

この問題は解決できますが、入力に表示されるとは思わないので、努力する価値はありません。

を使用すると、9番目のフィールドperlより正式な解析を実行することもできます。それは次のとおりです。

< file perl -F'\t' -lane '
  my %field;
  while ($F[8] =~ /(\w+) +"(.*?)"/g) {$field{$1}=$2}
  if (%field) {
    print join " ", @field{
      qw(gene_id transcript_id reference_id ref_gene_id
    )}
  }'

(ここでは、1つ以上の属性が見つかるたびに1行が印刷されます(他のメソッドによって要求されたすべての属性とは反対)。

関連情報