Shell-Script
基於第二個文件中的模式匹配的第一個文件的映射欄位
我有兩個製表符分隔的文件,我需要將文件 1 第一列中的文本與文件 2 行中的任何位置進行匹配。匹配後,我想列印文件 1 匹配行的第二列中的內容到文件 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)";
我們可以解析
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}
這將為您的範例列印正確的結果,但由於多種原因,這不是您想要的。第一個是它可能會在各種情況下失敗,比如
protein_1.p1
和protein_1.p11
。第二個原因是性能,file2 每一行的時間不是恆定的,而是file1
.所以我們要修改上面的腳本。您可能想為要匹配的蛋白質字元串定義一個正則表達式。這樣,匹配變得足夠嚴格,並且在第二次解析時,時間取決於匹配欄位上的正則表達式,而不是數組大小。
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
: “protein_” 後跟一個或多個數字,".p" 和一個或多個數字 所有這些都在 word 邊界內。點是字面意思。單詞字元是[:alnum:]
,_
所以其餘的都是邊界。- 還有一個健全性檢查的第一個欄位
file1
。- 如果
match()
找到 a ,則內置變數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)";