awk/bash删除具有唯一id的行,并将列中具有max/min值的行保留在同一id下
如果我们有以下输入,并且希望首先检测cpd_编号($2)在文件中是否唯一,请删除整行。在这种情况下,应删除带有“cpd-666”的行。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_编号”下,则只打印具有最大和最小“对数_比率”(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
输出:
说明:
- 使用核心模块(每个
binary都附带)来查找$17的最小值和最大值李>perl
- 使用
拆分-F
上的行,
选项将分隔符上的行拆分为一个-一个
数组李>@F
- 如果这是我们的第一行,我们就打印出来
- 我们创建一个散列,第二列作为键,第17列作为第二层键。该值为整行
- 我们创建一个计数器散列来保持第二列的计数
- 在
块中,我们从计数器散列遍历键。如果计数是一,我们跳过它END
- 如果计数器大于1,则打印第17列的最小值和最大值李>
#!/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]]
}
}
}