簡體   English   中英

如何使用awk根據數字范圍將特定值添加到列

[英]how to use awk to add specific values to a column based on numeric ranges

我正在嘗試根據bed_file數字向我的文件coverage_file添加一列。 在我的coverage_file我在第二列中有位置,並且bed_file包含從第二列到第三列的位置范圍,以及在第4列中的名稱。我想在bed_file范圍內,將每個位置的對應名稱添加到coverage_file中,並且也有編號,所以我可以區分同一對象上的多個位置范圍(重疊群)。 希望我的示例數據更加清晰:

#example data

#coverage file looks like:

#k141_xxx.xx are contigs (long sequences of DNA), where different genes can be found on.
#the second column is the current position on the individual contig
#the third column is the coverage on this position (not important here)
#the fourth column is the sample where the data comes from: A1..7 and B8..10

k141_102288 298 5 A4
k141_102288 298 5 A5
k141_102288 298 5 B8
k141_102288 298 5 B9
k141_102288 299 5 A4
k141_102288 299 5 A5
k141_102288 299 5 B9
k141_102288 300 5 A5
k141_102288 301 5 A5
k141_102511.0 8226 5 A5
k141_102511.0 8227 5 A5
k141_102511.0 8228 5 A5
k141_102511.0 8229 5 A5
k141_102511.0 8230 5 A5
k141_102511.0 8231 5 A5
k141_102511.0 8232 5 A5
k141_102511.0 8233 5 A5
k141_102511.0 8234 5 A5
k141_102511.0 9129 5 A6
k141_102511.0 9207 5 A6
k141_102511.0 9275 5 A7
k141_102511.0 9276 5 A7
k141_102511.0 9277 5 A7
k141_102511.0 9278 5 A7
k141_102511.0 9279 5 A7
k141_102511.0 9280 5 A7
k141_102511.0 9281 5 A7
k141_102511.0 9282 5 A7

#bed file looks like this
# the bed file shows the start $2 and end $3 position of a gene $4 on the contigs $1
k141_102288 2   301 phnE
k141_102511.0   7890    8807    phnE
k141_102511.0   8814    10400   phnE

#proposed output (note the two different regions of phnE on k141_102511.0)
k141_102288 298 5 A4    phnE_001
k141_102288 298 5 A5    phnE_001
k141_102288 298 5 B8    phnE_001
k141_102288 298 5 B9    phnE_001
k141_102288 299 5 A4    phnE_001
k141_102288 299 5 A5    phnE_001
k141_102288 299 5 B9    phnE_001
k141_102288 300 5 A5    phnE_001
k141_102288 301 5 A5    phnE_001
k141_102511.0 8226 5 A5 phnE_002
k141_102511.0 8227 5 A5 phnE_002
k141_102511.0 8228 5 A5 phnE_002
k141_102511.0 8229 5 A5 phnE_002
k141_102511.0 8230 5 A5 phnE_002
k141_102511.0 8231 5 A5 phnE_002
k141_102511.0 8232 5 A5 phnE_002
k141_102511.0 8233 5 A5 phnE_002
k141_102511.0 8234 5 A5 phnE_002
k141_102511.0 9129 5 A6 phnE_003
k141_102511.0 9207 5 A6 phnE_003
k141_102511.0 9275 5 A7 phnE_003
k141_102511.0 9276 5 A7 phnE_003
k141_102511.0 9277 5 A7 phnE_003
k141_102511.0 9278 5 A7 phnE_003
k141_102511.0 9279 5 A7 phnE_003
k141_102511.0 9280 5 A7 phnE_003
k141_102511.0 9281 5 A7 phnE_003
k141_102511.0 9282 5 A7 phnE_003

我試圖利用以前遇到過的類似問題,但是仍然無法弄清楚它是如何工作的: 如何使用一個文件中子字符串位置的信息從另一個文件中提取子字符串(循環,bash)

有什么建議么? 編輯:我試圖去沒有建議。 2由@ Nic3500提供,但我無法運行它。 我在最后一行中有一個意外的令牌。 到目前為止,這是我想出的:

#!bin/bash

# We are reading two files: coverage_file.txt and intersect.bed
# NR is equal to FNR as long as we are reading the
# first file.
# Store the positions in an array current_position from the coverage file (indexed by $1)
# go to bed file
# store the start and end positions and the gene names in similar arrays
# if current_position is between start_pos and end_pos, print additionally gene name 

awk 'NR==FNR{current_position[$1]=$2} 
NR==FNR{next}
{start_pos[$1]=$2;end_pos[$1]=$3;gene_name[$1]=$4}
{if(current_position[$1] >= start_pos[$1]) && (current_position[$1] <= `end_pos[$1]){ print $1,$2,$3,$4,gene_name[$1]}}' coverage_file.txt intersect.bed > test.txt`

awk解救!

 $ awk 'NR==FNR{start[NR]=$2; end[NR]=$3; key[$1,$2]=$4 sprintf("_%03d",NR); next}
           {for(i in start)
              {s=start[i];
               if(s<=$2 && $2<=end[i] && ($1,s) in key) print $0,key[$1,s]}}' bed coverage 

解釋在讀取第一個文件( NR==FNR部分)時,創建以行號索引的數組以開始和結束范圍。 我們需要將范圍與鍵相關聯,因此創建一個以鍵為索引的地圖並為每個范圍開始。 這里也有機會使用行號計數器和最后一個字段作為標簽來創建索引標簽,將數字格式設置為零填充三位數字。

為了處理第二個文件(現在為第二個語句),我們遍歷所有開頭以找到匹配的結尾並驗證鍵,范圍開頭是有效的組合,打印添加了格式后綴的行。

通過使用鍵索引起始值可以提高效率,但是會使代碼復雜化。 如果您的“床”文件不是很大,那應該不是問題。 也有意打印所有匹配的條目,而不是第一個,以驗證范圍不重疊。 否則,請脫機進行驗證,並通過在第一次匹配/打印后中斷來提高速度。 同樣,如果對起始值進行了排序,則錯過起始范圍時可以提前退出循環。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM