awk/bash删除具有唯一id的行,并将列中具有max/min值的行保留在同一id下

awk/bash删除具有唯一id的行,并将列中具有max/min值的行保留在同一id下,bash,awk,count,max,min,Bash,Awk,Count,Max,Min,如果我们有以下输入,并且希望首先检测cpd_编号($2)在文件中是否唯一,请删除整行。在这种情况下,应删除带有“cpd-666”的行。 第二,如果有多行保存在同一“cpd_编号”下,则只打印具有最大和最小“对数_比率”(17美元)的两行 理想的输出应该是 targetID,cpd_number,Cell_assay_id,Cell_alt_assay_id,Cell_type_desc,Cell_Operator,Cell_result_value,Cell_unit_value,assay_i

如果我们有以下输入,并且希望首先检测cpd_编号($2)在文件中是否唯一,请删除整行。在这种情况下,应删除带有“cpd-666”的行。
第二,如果有多行保存在同一“cpd_编号”下,则只打印具有最大和最小“对数_比率”(17美元)的两行

理想的输出应该是

targetID,cpd_number,Cell_assay_id,Cell_alt_assay_id,Cell_type_desc,Cell_Operator,Cell_result_value,Cell_unit_value,assay_id,alt_assay_id,type_desc,operator,result_value,unit_value,Ratio_operator,Ratio,log_ratio,Cell_experiment_date,experiment_date,Cell_discipline,discipline
49,cpd-7788990,1212,2323, IC50 ,,100,uM,1334,1331,Ki,,10,uM,,10,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-7788990,8888,9999, IC50 ,,200,uM,1334,1331,Ki,,10,uM,,20,-1.301029996,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme

我试图使用awk count函数,但它似乎工作得不太好。任何一位古鲁都能给出一些评论吗?谢谢

如果您可以尝试使用
perl
,就会更容易:

perl -MList::Util=max,min -F, -lane '
    print if $.==1;
    $line{$F[1]}{$F[16]}=$_; 
    $count{$F[1]}++ 
}{
    for $key (keys %count) {
        next if $count{$key}==1; 
        print $line{$key}{ max keys %{$line{$key}} };
        print $line{$key}{ min keys %{$line{$key}} }
     }
' file
输出: 说明:
  • 使用核心模块(每个
    perl
    binary都附带)来查找$17的最小值和最大值
  • 使用
    -F
    拆分
    上的行
  • -一个
    选项将分隔符上的行拆分为一个
    @F
    数组
  • 如果这是我们的第一行,我们就打印出来
  • 我们创建一个散列,第二列作为键,第17列作为第二层键。该值为整行
  • 我们创建一个计数器散列来保持第二列的计数
  • END
    块中,我们从计数器散列遍历键。如果计数是一,我们跳过它
  • 如果计数器大于1,则打印第17列的最小值和最大值
虽然没有perl答案那么简洁,但这里有一个可执行的awk文件:

#!/usr/bin/awk -f

BEGIN { FS="," }

NR==1 {print; next}

{
  a[$2,$17]=$0

  h=high[$2]
  high[$2]=$17>h || h=="" ? $17 : h

  l=low[$2]
  low[$2]=$17<l || l=="" ? $17 : l
}

END {
  for(i in high) {
    if(low[i]!=high[i]) {
      print a[i,high[i]]
      print a[i,low[i]]
    }
  }
}
#/usr/bin/awk-f
开始{FS=“,”}
NR==1{打印;下一个}
{
a[$2,$17]=$0
h=高[$2]
高[$2]=$17>h | | h==“”?$17:h
l=低[$2]

low[$2]=$17您还应该发布您制作的awk脚本。这也有帮助。这个perl解决方案看起来非常优雅。我需要学习一点来详细阅读这个脚本,因为我对perl一无所知。这个解决方案也很优雅。您能解释一下这行吗?“$high[$2]=$17>h | h==”“?$17:h”和“low[$2]=$17当然。
h
已分配给
high[$2]
。未分配数组的默认查找为“”,因此h将为“”或以前分配的值。
high[]
行使用a,其中条件为an或(
|
)在
$17>h
(大于)或
h=>“
为真。如果其中一个为真,则将
$17
分配给
高[$2]
。如果不是,则将
h
重新分配回
高[$2]
低[]
code与之类似,但对
$17的测试感谢您解释了晦涩难懂的awk行。请问您是从哪里学到这些更高级的awk的?边做边学还是有推荐书?我读过的所有awk教程都更像是中级教程。不过,对于阅读,我建议使用“awk编程语言”虽然我很久以前就买了我的,但它很便宜。我看到这里的其他人建议“有效的awk编程”,虽然我从来没有见过一个副本。主要是通过这样做。你可以把这个网站当作一个教程,从“家庭游戏版”中挑选问题并尝试自己解决(无需先阅读其他答案,也无需张贴答案,直到您感觉舒服为止)。寻找具有定义良好的输入/输出的问题。祝你好运!@Chubaka不幸的是,随着perl和python等高级脚本语言的日益流行,awk已经稳步下降。没有任何新书,因此你最好的选择是学习免费提供的GNU awk用户手册。人们通常会因为可移植性。在这个网站上学习awk问题和答案也会有帮助
targetID,cpd_number,Cell_assay_id,Cell_alt_assay_id,Cell_type_desc,Cell_Operator,Cell_result_value,Cell_unit_value,assay_id,alt_assay_id,type_desc,operator,result_value,unit_value,Ratio_operator,Ratio,log_ratio,Cell_experiment_date,experiment_date,Cell_discipline,discipline
49,cpd-7788990,1212,2323, IC50 ,,100,uM,1334,1331,Ki,,10,uM,,10,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-7788990,8888,9999, IC50 ,,200,uM,1334,1331,Ki,,10,uM,,20,-1.301029996,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
#!/usr/bin/awk -f

BEGIN { FS="," }

NR==1 {print; next}

{
  a[$2,$17]=$0

  h=high[$2]
  high[$2]=$17>h || h=="" ? $17 : h

  l=low[$2]
  low[$2]=$17<l || l=="" ? $17 : l
}

END {
  for(i in high) {
    if(low[i]!=high[i]) {
      print a[i,high[i]]
      print a[i,low[i]]
    }
  }
}