Bash awk单独的行,如果$2相同,最大值和最小值<;=1“;及$2相同,最大值和最小值<;1“;

Bash awk单独的行,如果$2相同,最大值和最小值<;=1“;及$2相同,最大值和最小值<;1“;,bash,csv,awk,Bash,Csv,Awk,如果我们有一个输入文件:input.csv cpdID,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

如果我们有一个输入文件:input.csv

cpdID,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,5555,6666, IC50 ,>,150,uM,1334,1331,Ki,,10,uM,>,15,-2,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,-3,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-6666666,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1.1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1.2,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1.3,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
我们想将这个input.csv分为两个文件,以便我们可以执行以下步骤:“如果$2与$17 1中的最大值减去最小值相同,则对行进行平均”,将其放入另一个文件中

outfile2.csv(其中$17中的最大和最小值=-1-(-3)=2>1)

下面是从以下链接进行修改的尝试


由于未知原因,此脚本无法正确打印中间范围值。我可以知道是否有大师有意见/解决方案吗

看看这个,这是一个处理每个组id变化的示例:

#!/usr/bin/awk -f

BEGIN {FS=","; f1="a"; f2="b"}

FNR==1 { print $0 > f1; print $0 > f2; next }

$2!=last_id && FNR > 2 { handleBlock() }

{ a[++cnt]=$0; m[cnt]=$17; last_id=$2 }

END { handleBlock() }

function handleBlock() {
  if( m[1]-m[cnt]<=1 ) fname = f1
  else fname = f2
  for( i=1;i<=cnt;i++ ) { print a[i] > fname }
  cnt=0
}
考虑到这一点,下面是对脚本的分解:

  • BEGIN
    块中设置
    FS
    和一些输出文件名(“a”和“b”用于我的测试)
  • 第一行是标题-将其放在每个文件中,
    f1
    f2
  • 如果
    $2!=最后一个id
    ,调用
    handleBlock()
    函数对其进行处理
  • 将整行存储在数组
    a
    、数组
    m
    中的
    $17
    ,并设置
    last\u id=$2
    (数组名称非常糟糕)
  • cnt
    变量表示每个组中有多少个条目(我称之为块)
  • handleBlock()
    仅在
    $2
    id更改时或在文件末尾调用,以捕获
    end
    块中的最后一个组
  • handleBlock()使用
    m
    (max为
    m[1]
    ,min为m[cnt])测试OP的状态,以确定输出文件名,然后将
    a`中的所有元素打印到所选文件名

我感到惊讶的是,即使是跑步。我认为
a
不是一个有效的awk语句。将该比较分为两部分,看看是否有效。amid数组来捕获所有非最小/最大值的行,这些行不起作用,因为
mid
将只包含一行。此外,
a
将只捕获每个
$2,$17的唯一组合。如果文件按
$2
分组(看起来是这样),那么当
$2
更改文件时,您可以使用更直接的测试技术来决定如何操作数据。我明白了。因此,即使我们给中间数组一个范围,也无法在awk中获得多行。“如果文件按$2分组(看起来是这样),那么当文件中$2发生变化时,您可以使用更直接的测试技术来决定如何操作数据。”您能提供一些示例吗“当$2发生变化时的直接测试技术”?谢谢。谢谢你的评论!但是,当“awk-f average2.awk input.csv”时,似乎没有生成任何内容。我想我们可能需要等待你的详细解释才能完全理解此脚本并对其进行修改。你为什么调用
handleBlock()
在线以及在
结尾处
?这不总是打印最后一行吗?@ssdecontrol-在看到整个组之前,不会打印任何组。
把手()
用于捕获最后一个组,该组的结束只能通过到达的文件的结束来知道。当注释掉
end
块时,只有
cpd-66666
数据行写入
a
。这确实是一种优雅的方法。只需仔细检查一下:handleBlock()awk内置函数不是吗?谷歌搜索没有任何提示。@Chubaka-该函数在
function handleBlock(){…}
code中的文件末尾本地定义。函数是放置多次调用的代码的好地方。这里是指向GNU awk文档的链接。
cpdID,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,5555,6666, IC50 ,>,150,uM,1334,1331,Ki,,10,uM,>,15,-2,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,-3,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

  m=mid[$2]
  mid[$2]=l<$17<h || m=="" ? $17 : m

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

END {
  for(i in high) {
    if(high[i]-low[i]<=1) {
      print a[i,high[i]]
      print a[[i,mid[i]]
      print a[i,low[i]]
    }
  }
}
cpdID,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-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-1111,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1.3,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-6666666,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-6666666,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
49,cpd-6666666,8888,9999, IC50 ,,400,uM,1334,1331,Ki,,10,uM,,40,-1,12/6/2006 0:00,2/16/2007 0:00,Cell,Enzyme
#!/usr/bin/awk -f

BEGIN {FS=","; f1="a"; f2="b"}

FNR==1 { print $0 > f1; print $0 > f2; next }

$2!=last_id && FNR > 2 { handleBlock() }

{ a[++cnt]=$0; m[cnt]=$17; last_id=$2 }

END { handleBlock() }

function handleBlock() {
  if( m[1]-m[cnt]<=1 ) fname = f1
  else fname = f2
  for( i=1;i<=cnt;i++ ) { print a[i] > fname }
  cnt=0
}
a
a
a
b <- this is a good place to process all the prior "a" entries
b
c <- process "b" entries here
c
EOF <- the end of the file.  process the last group ( the "c" entries here )