2つのタブで区切られたファイルがあり、ファイル1の最初の列のテキストを次のように変換する必要があります。どのファイルの2行目の場所です。一致した後、ファイル1から一致する行の2番目の列の内容をファイル2の一致する行の終わりまで印刷したいと思います(以下の例)。
私はこれがawkを使用してほぼ確実に実行できることを知っていますが、awkまたはsedにはあまりうまくいかず、ここで関連する質問を検索してそのスクリプトを適用しようとしました。どんなアドバイスも本当にありがとうございます。
ファイル1
protein_1.p1 note "PJD5F7, match to databaseID=64575, (species X)";
protein_1.p2 note "PJD5F7, match to databaseID=64575, (species X)";
protein_3.p1 note "PA5F9H, match to databaseID=93689, (species W)";
protein_4.p1 note "Q7GT5J, match to databaseID=89045, (species Y)";
protein_4.p3 note "YE6G3L, match to databaseID=44968, (species Z)";
ファイル2
chromosome_1 programID transcript_id "protein_1.p1"; parent "protein_1";
chromosome_1 programID transcript_id "protein_1.p2"; parent "protein_1";
chromosome_1 programID transcript_id "protein_2.p1"; parent "protein_2";
chromosome_1 programID transcript_id "protein_2.p2"; parent "protein_2";
chromosome_1 programID transcript_id "protein_3.p1"; parent "protein_3";
chromosome_1 programID transcript_id "protein_4.p1"; parent "protein_4";
chromosome_1 programID transcript_id "protein_4.p2"; parent "protein_4";
chromosome_1 programID transcript_id "protein_4.p3"; parent "protein_4";
希望の出力
chromosome_1 programID transcript_id "protein_1.p1"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1 programID transcript_id "protein_1.p2"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1 programID transcript_id "protein_2.p1"; parent "protein_2";
chromosome_1 programID transcript_id "protein_2.p2"; parent "protein_2";
chromosome_1 programID transcript_id "protein_3.p1"; parent "protein_3"; note "PA5F9H, match to databaseID=93689, (species W)";
chromosome_1 programID transcript_id "protein_4.p1"; parent "protein_4"; note "Q7GT5J, match to databaseID=89045, (species Y)";
chromosome_1 programID transcript_id "protein_4.p2"; parent "protein_4";
chromosome_1 programID transcript_id "protein_4.p3"; parent "protein_4"; note "YE6G3L, match to databaseID=44968, (species Z)";
答え1
file1
を解析し、$2
値()をキー($1
)にマッピングし、行(file2
)の一部がキーと一致する場合は、解析して$3
値を行に追加できます。
BEGIN {OFS = FS = "\t"}
FNR == NR {arr[$1] = $2; next}
{for (x in arr) if ($3 ~ x) {$0 = $0 " " arr[x]; break}}
{print}
これはあなたの例の正しい結果を印刷しますが、いくつかの理由で望ましい結果ではありません。 1つ目は、などさまざまな状況で失敗する可能性があるということprotein_1.p1
ですprotein_1.p11
。 2番目の理由はパフォーマンスです。 file2の各行の時間は一定ではありませんが、サイズは〜ですfile1
。
したがって、上記のスクリプトを変更する必要があります。タンパク質文字列と一致する正規表現を定義できます。これにより、一致が十分に厳しくなり、2番目の解析では、時間は配列サイズではなくフィールドの正規表現の一致に依存します。
BEGIN {OFS = FS = "\t"; re = "\\<protein_[[:digit:]]+.p[[:digit:]]+\\>"}
FNR == NR {if ($1 ~ re) arr[$1] = $2; next}
match($3, re) {$0 = $0 " " arr[substr($3,RSTART,RLENGTH)]}
{print}
メモ:
re
:「タンパク質_」の後に、1つ以上の数字、「.p」、および1つ以上の数字がすべて、これらの内部単語境界内にあります。ドットは文字通りです。単語文字は[:alnum:]
、残りは_
境界です。- また、最初のフィールドに対して完全性チェックが行われます
file1
。 - aが見つかると、
match()
組み込み変数は一致する文字列のインデックスと長さをRSTART
保持し、RLENGTH
この部分文字列はハッシュに使用されます。
使用法:
> awk -f tst.awk file1 file2
chromosome_1 programID transcript_id "protein_1.p1"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1 programID transcript_id "protein_1.p2"; parent "protein_1"; note "PJD5F7, match to databaseID=64575, (species X)";
chromosome_1 programID transcript_id "protein_2.p1"; parent "protein_2";
chromosome_1 programID transcript_id "protein_2.p2"; parent "protein_2";
chromosome_1 programID transcript_id "protein_3.p1"; parent "protein_3"; note "PA5F9H, match to databaseID=93689, (species W)";
chromosome_1 programID transcript_id "protein_4.p1"; parent "protein_4"; note "Q7GT5J, match to databaseID=89045, (species Y)";
chromosome_1 programID transcript_id "protein_4.p2"; parent "protein_4";
chromosome_1 programID transcript_id "protein_4.p3"; parent "protein_4"; note "YE6G3L, match to databaseID=44968, (species Z)";