web-dev-qa-db-ja.com

各列の行から文字列の一部を抽出します

次のように、20.000行を超えるテキストファイルがあります。

7   128550681   128550681   Intron:1:36:RETAINED-RETAINED;Transcript:NM_001135914.1;Gene:KCP:protein_coding 1   1   0   0
1   17718672    17718672    Intron:9:16:RETAINED-RETAINED;Transcript:NM_207421.4;Gene:PADI6:protein_coding  1   1   0   0
1   17718672    17718672    Intron:9:16:RETAINED-RETAINED;Transcript:NM_207421.4;Gene:PADI6:protein_coding  1   1   0   0
4   86035   86035   Exon:4:5:RETAINED;Transcript:NM_001286052.1;Gene:ZNF595:protein_coding  1   1   0   0
3   12942851    12942851    Intron:14:14:SKIPPED-ALTTENATIVE_3SS;Transcript:NM_001134382.2;Gene:IQSEC1:protein_coding   1   1   0   0

必要なのは、4番目の列にGene:genenameだけが含まれているため、出力は次のようになります。

7   128550681   128550681   Gene:KCP    1   1   0   0
1   17718672    17718672    Gene:PADI6  1   1   0   0
1   17718672    17718672    Gene:PADI6  1   1   0   0
4   86035   86035   Gene:ZNF595 1   1   0   0
3   12942851    12942851    Gene:IQSEC1 1   1   0   0

*問題はGene:genenameまたは:で分割しようとしたときに;が常に同じ場所にあるとは限らないことです

特定の列を選択する方法、パターンを含む行をgrepする方法など、非常に基本的なawk/sedを知っています。

2
LamaMo

次のawkコマンドでこれを達成できました。

awk '{sub(/^.*;/,"",$4); print}' input

これにより、列4の最後の;までのすべてが削除され、機能しない可能性があります(steeldriverのコメントを参照)。その場合は、質問を明確にして更新してください。

2
jesse_b

POSIXで定義された構成のみでawkを使用すると、

awk 'match($4, /Gene:(.+)\:/){ $4=substr($4, RSTART, RLENGTH-1) }1' file

出力をもう少しきちんと揃えるには、出力を| column -tにパイプします。これにより、列がタブで区切られます。行内のGene:genenameの位置がわからない場合は、awkを変更して行内の任意のパターンを探し、4番目の列を必要な値で変更します。 $4から$0(行全体)に変更すると、問題なく動作するはずです。

awk 'match($0, /Gene:(.+)\:/){ $4=substr($0, RSTART, RLENGTH-1) }1' file
2
Inian
Perl -pale 's#(?:\H+\h+){3}\K\H+#($F[3] =~ /(?:^|;)(Gene:[^:]+)/)[0]#e' input-file.txt 

°4番目のフィールドに遺伝子の位置が固定されていない場合は、上記のように実行できます。

°正規表現(?:\H+\h+){3}\K\H+を使用して4番目のフィールドに焦点を合わせ、それをs///eコマンドの代替部分で使用されている別の正規表現にすぐに置き換えます。

0
Rakesh Sharma

Perl:

_Perl -F'\h+' -lane '
    for ( $F[3] ) {
        my $a = index(";$_", ";Gene:"     );
        my $b = index(";$_", ":",    $a+6 );
        $_ = substr(";$_", $a+1, $b-$a-1);
    }
    print join "\t", @F;
' input-file.txt
_

出力:

_7   128550681   128550681   Gene:KCP    1   1   0   0
1   17718672    17718672    Gene:PADI6  1   1   0   0
1   17718672    17718672    Gene:PADI6  1   1   0   0
4   86035   86035   Gene:ZNF595 1   1   0   0
3   12942851    12942851    Gene:IQSEC1 1   1   0   0
$   128550681   128550681   Gene:$$$    1   1   0   0
_

説明:

  • Perlオプション:
    • _-n_ =>入力の行ごとの読み取りを呼び出します。
    • _-F_ =>は_FS = horizontal whitespace_になります。
    • _-a_ =>各行をフィールドに分割し(FSは_-F_オプションまたはデフォルトで単一のスペースによって設定されたものに基づいて))、配列_@F_。
    • _-l_ =>は_RS = ORS = "\n"_になります。
    • _-e_ =>以下はPerlコードとして扱われ、各行、つまりレコードに適用されます。
  • _data structures_関与:
    • _@F_ =>レコードを分割して取得したフィールドが入力された配列。 0からインデックスが付けられます。したがって、_$F[3]_はレコードの4番目のフィールドです。
    • _$a_ =>は、4番目のフィールドの部分文字列_;Gene:_の位置を保持します。
    • _$b_ =>は、4番目のフィールドの部分文字列_:_の位置を保持します。これは、_;Gene:_の位置の6桁後に表示されます。 IOW、_:_の後に2番目の_;Gene_が見つかります。注:_$F[3]_の位置はどこにでも配置できるため、検索文字列、つまり_Gene:_にセミコロンを埋め込みます。したがって、4番目のフィールドの先頭にも配置できます。これは、その不測の事態に対処するためです。
    • _$__ =>は、ローカライズされたバージョンの_$F[3]_をforループ内に保持します。 substrビルトインは、_gene:..._情報を抽出し、それを_$F[3]_に保存します。
    • 注:_$a,$b_の変数定義の前のmy修飾子は、スコープがforループのみに制限されている字句変数としてマークします。
    • 注:forループ内の_$__は、現在のレコード/行を参照しません。 forループの期間中はオーバーロードされてローカライズされて_$F[3]_になりました。

GNU Sed:

_sed -Ee '
    s/\S+/\n&\n/4
    s/\n(.*;)?(Gene:[^:]+):.*\n/\2/
' input-file.txt
_

説明:

  • 4番目のフィールドを改行でマークします。
  • 現在の行の領域を杭打ちした後、必要なデータ(この場合は_Gene:_)を取り出し、その後_as many non colons we meet on the way before we hit the next colon_を取り出します。
  • この方法は、さまざまなフィールド間に存在する間隔を乱しません。これは重要な場合と重要でない場合があります。
  • 注参考:4番目のフィールドに単一の遺伝子があると想定しています。複数の遺伝子の場合、エラーや警告は発生せず、そのレコードの4番目のフィールドの最後の遺伝子を静かに選択します。
0
Rakesh Sharma

列4を;または:で区切られた文字列のリストとして扱い、最初にそのフィールドを分割して、列全体を文字列Geneと次の文字列(遺伝子名)に置き換えます。そして、必要なビットを見つけます。

$ awk -vOFS='\t' '{ split($4,a,"[;:]"); for (i in a) if (a[i]=="Gene") { $4 = a[i] ":" a[i+1]; break } } 1' file
7       128550681       128550681       Gene:KCP        1       1       0       0
1       17718672        17718672        Gene:PADI6      1       1       0       0
1       17718672        17718672        Gene:PADI6      1       1       0       0
4       86035   86035   Gene:ZNF595     1       1       0       0
3       12942851        12942851        Gene:IQSEC1     1       1       0       0
0
Kusalananda