将 if 条件应用于制表符分隔文件中特定列中具有相同值的所有行:

将 if 条件应用于制表符分隔文件中特定列中具有相同值的所有行:

基本上我想在第 2 列中具有相同值的行中应用 if 条件。在示例中,前三行在第 2 列 (Disease1) 中具有相同的值。现在,对于这三行,我想应用 IF 条件 - 如果第三列为“高”,则仅将该行写入输出文件。如果第三列没有“高”,则查找“中”并打印它。如果“中”也不存在,则打印包含“低”值的行。

输入:

id1 Disease1 High
id2 Disease1 Medium
id3 Disease1 Low
id4 Disease2 Low
id5 Disease3 Medium
id6 Disease3 Low

预期输出:

id1 Disease1 High
id4 Disease2 Low
id5 Disease3 Medium

答案1

awk 'BEGIN { FS=OFS="\t"; d["High"]=1; d["Medium"]=2; d["Low"]=3 } { print d[$3], $0 }' file |
sort -t $'\t' -k3,3 -k1,1n | sort -t $'\t' -s -u -k3,3 | cut -f 2-

不幸的是,单词“High”、“Medium”和“Low”并未按此顺序按字母顺序排序,因此我们在每行前面为第 3 列中的相应单词添加整数 1、2 和 3。awk脚本。该整数与原始内容之间用制表符分隔,表示疾病的严重程度(1 最高)。

然后,我们对疾病和该整数字段的修改数据进行排序,以便记录按疾病分组并按严重程度排序。

然后,我们仅将疾病作为关键(第二个sort)进行“独特排序”。这会丢弃任何重复的疾病,对于每种疾病,我们只留下最严重的记录。它们使用稳定的排序算法,保留具有相同键的记录的重新排序-ssort

最后cut的 删除了我们之前添加的整数awk

管道假定使用 来bash指定命令的字段分隔符sort。如果bash未使用,请插入单引号文字制表符而不是使用$'\t'(您可能可以通过按 来执行此操作Ctrl+V Tab)。

答案2

如果每个 Id(以秒为单位)列的优先级始终从高到低,那么可以通过以下方式轻松完成:

sort -u -k2,2 infile

否则你可以这样做:

sed 's/High$/1/; s/Medium$/2/; s/Low$/3/' infile \
| sort -k2,3  \
| sort -uk2,2 \
| sed 's/1$/High/; s/2$/Medium/; s/3$/Low/'

或者只是awk

awk '{ pr[$2]=($3=="High"?$3:(pr[$2]=="High"?pr[$2]:(pr[$2]=="Medium"?pr[$2]:$3)));
       if (temp!=pr[$2]) { id[$2]=$0; temp=pr[$2] }
} END { for (key in id) print id[key] }' infile

答案3

我将使用 Perl 并构建一个解析器,这将创建这个哈希:

  • 第 2 列值作为键
  • 对应于键的第一行将构成该键的值
  • 设置值后,将跳过某个键的所有其他行

解析完成后,我将打印哈希值,如果需要的话对第二个标记进行排序。

答案4

只需 awk

awk '
    BEGIN {prio["High"]=1; prio["Medium"]=2; prio["Low"]=3}
    !($2 in p) || prio[$3] < p[$2] {p[$2] = prio[$3]; line[$2] = $0}
    END {for (key in line) print line[key]}
' file
id1 Disease1 High
id4 Disease2 Low
id5 Disease3 Medium

相关内容