awk - 如何比较一个字段中具有相同唯一子字符串的行并仅保留最后一个字段中具有最大数字的行?
问题描述
我有一个文件,其格式为一系列唯一标识符 ( >lcl|ORF#_URS[:alnum:]:##:## foo, bar:##
) 段,后跟相应的 alpha 字符串 ( ALPHAALPHAALPHA:::0
) 在其正下方的行上。文件样本:
>lcl|ORF1_URS0000000001:102:197 unnamed protein product:95
MVVGDNARKRTLIPHTSYGRKQGTFGPCAIR:::0
>lcl|ORF2_URS0000000001:1:93 unnamed protein product, partial:92
LNAGGRPNTCKSSGREKLASLESGGRVSNA:::0
>lcl|ORF3_URS0000000001:8:82 unnamed protein product:74
MAAGLTHASRAVERSLLLLRAADG:::0
>lcl|ORF4_URS0000000001:86:118 unnamed protein product:32
MPRNLPGSGG:::0
>lcl|ORF5_URS0000000001:193:152 unnamed protein product:41
MIAQGPKVPCFLP:::0
>lcl|ORF6_URS0000000001:167:135 unnamed protein product:32
MLSPVGRMRY:::0
>lcl|ORF7_URS0000000001:32:0 unnamed protein product, partial:32
MHVLGLPPAFN:::0
>lcl|ORF1_URS00000000M3:42:77 unnamed protein product:35
MINALCSYLLA:::0
>lcl|ORF2_URS00000000M3:174:236 unnamed protein product:62
MRGRSPTLVLRHGPDFYGRQ:::0
>lcl|ORF3_URS00000000M3:246:311 unnamed protein product:65
MDNGGNSDPAMPREGRRPYGL:::0
解决此问题需要重点关注的关键元素是字母数字URS 标识符和以“>”开头并以“:”分隔的行的最后一个字段 ( $4 ) 。
我想只保留每个唯一字母数字 URS 标识符(例如 ,URS0000000001
等URS00000000M3
)在同一行的最后一个字段中具有最大值的行(始终以“”开头并以“ >
”分隔:
)。如果同一标识符的最终字段中有两行或多行具有相同值,则取第一行或最后一行(无关紧要)。所需输出的示例:
>lcl|ORF1_URS0000000001:102:197 unnamed protein product:95
>lcl|ORF3_URS00000000M3:246:311 unnamed protein product:65
或者,如果它更简单:
URS0000000001 95
URS00000000M3 65
这远远超出了我的能力awk
,但我觉得我的逻辑已经完成了一半。我尝试编写一个awk
命令,搜索以“”开头的每一行,并在大于具有相同 URS 标识符的另一行时>
打印该行:$4
$4
awk -F":" 'BEGIN {OFS=FS} /^ *>/ {if (substr($1,11)==substr($1,11)){$4>$4}} 1' file
必须有更好的方法来匹配不同行上字段 ( ) 的子字符串$1
,以便随后将链接/关联字段 ( $4
) 与进行比较awk
。想法?
解决方案
请您尝试以下方法:
awk -F ":" '
NR==FNR { # 1st loop to find the maximum valued line for each id
if (match($1, "URS[[:alnum:]]+")) { # check if $1 matches the format
id = substr($1, RSTART, RLENGTH) # extract the id
if ($4 > a[id]) { # if $4 > max
a[id] = $4 # update the max value
b[id] = $1 # memorize the corresponding $1
}
}
next
}
{ # 2nd loop to print the maximum valued line for each id
if (match($1, "URS[[:alnum:]]+")) {
id = substr($1, RSTART, RLENGTH)
if ($1 == b[id]) print
}
}
' file file
输出:
>lcl|ORF1_URS0000000001:102:197 unnamed protein product:95
>lcl|ORF3_URS00000000M3:246:311 unnamed protein product:65
如果更简单的输出足够好并且您不介意出现的顺序,则可以使用更简单的替代方法:
awk -F ":" '
NR==FNR {
if (match($1, "URS[[:alnum:]]+")) {
id = substr($1, RSTART, RLENGTH)
if ($4 > a[id]) a[id] = $4
}
next
}
END {
for (i in a) print i, a[i]
}
' file
输出:
URS00000000M3 65
URS0000000001 95
推荐阅读
- javascript - 如何防止 Nestjs 上的事件循环冻结?
- java - 如何在 MacOS 上的 NetBeans 中创建 Java 应用程序?
- c - 从 C 中 for 循环中的 if 语句转储堆栈跟踪
- c# - WPF - 显示以 BitmapImage 作为源的图像时出现问题
- neo4j - 在 Neo4j 中调整标签字体的大小
- javascript - 如何更新反应状态
- azure - Azure IoT HTTP 支持
- node.js - 找不到未处理的“错误”事件 ETIMEDOUT 的起源
- linux - Debain 软件包重建
- javascript - 用户单击按钮时加载数据(缺少最后一行)