Awk查找每个键的最大值和最小值

Awk查找每个键的最大值和最小值,awk,Awk,我的数据如下所示: A学校和B学校每个班级的最高和最低期中成绩(未显示班级) 我想像这样合并它: schoolA 99 48 schoolB 94 36 awk -v OFS='\t' '$1 in min{min[$1]=$3<min[$1]?$3:min[$1] max[$1]=$2>max[$1]?$2:max[$1] next } {min[$1]=$3;max[$1]=$2}

我的数据如下所示: A学校和B学校每个班级的最高和最低期中成绩(未显示班级)

我想像这样合并它:

schoolA   99       48
schoolB   94       36
awk -v OFS='\t' '$1 in min{min[$1]=$3<min[$1]?$3:min[$1]
               max[$1]=$2>max[$1]?$2:max[$1]
               next } {min[$1]=$3;max[$1]=$2}
            END{for(x in min)print x, max[x], min[x]}' file
显示每个学校的最大值和最小值。 我试过这样的方法:

awk '
BEGIN{getline;min=$3;max=$2} 
{($3<min)?min=$3:"";($2>max)?max=$2:""} 
END{OFS="\t";print $1,max,min}
'
awk'
开始{getline;最小值=$3;最大值=$2}
{($3max)?max=$2:“}
结束{OFS=“\t”打印$1,最大值,最小值}
'
它成功了;但是,它有时会在最小值(第三列)自动加上一个点


有人能教我如何正确地做这件事,并解释一下上面的代码是什么意思吗?(特别是“getline”)这个代码可以按第一列(学校)合并行吗?

首先,我不认为你的
(条件)?var=1:2
是正确的。例如:

awk 'BEGIN{(3>5)?a=1:2;print a}'
什么也不输出。应该用以下文字书写:

$ awk 'BEGIN{a=(3>5)?1:2;print a}' 
2
  • 您不需要
    getline
  • 您没有检查
    学校
    ,因此您的代码将从所有学校值中找到最小/最大值。这不是你想要的
对于您的问题,您可以这样写:

schoolA   99       48
schoolB   94       36
awk -v OFS='\t' '$1 in min{min[$1]=$3<min[$1]?$3:min[$1]
               max[$1]=$2>max[$1]?$2:max[$1]
               next } {min[$1]=$3;max[$1]=$2}
            END{for(x in min)print x, max[x], min[x]}' file
awk-vofs='\t'$1最小值{min[$1]=$3max[$1]?$2:max[$1]
下一个}{min[$1]=$3;max[$1]=$2}
结束{对于(最小值x)打印x,最大值[x],最小值[x]}文件

首先,我不认为你的
(条件)?var=1:2是正确的。例如:

awk 'BEGIN{(3>5)?a=1:2;print a}'
什么也不输出。应该用以下文字书写:

$ awk 'BEGIN{a=(3>5)?1:2;print a}' 
2
  • 您不需要
    getline
  • 您没有检查
    学校
    ,因此您的代码将从所有学校值中找到最小/最大值。这不是你想要的
对于您的问题,您可以这样写:

schoolA   99       48
schoolB   94       36
awk -v OFS='\t' '$1 in min{min[$1]=$3<min[$1]?$3:min[$1]
               max[$1]=$2>max[$1]?$2:max[$1]
               next } {min[$1]=$3;max[$1]=$2}
            END{for(x in min)print x, max[x], min[x]}' file
awk-vofs='\t'$1最小值{min[$1]=$3max[$1]?$2:max[$1]
下一个}{min[$1]=$3;max[$1]=$2}
结束{对于(最小值x)打印x,最大值[x],最小值[x]}文件
如果可以:

$datamash-W-g1最大2分钟3
  • -W
    使用空格作为分隔符
  • -g1
    按第一个字段分组
  • 最大2最小3
    第二个字段的最大值和第三个字段的最小值
  • 如果输入文件包含标题行,请在
选项中使用
--header忽略它
如果可以:

$datamash-W-g1最大2分钟3
  • -W
    使用空格作为分隔符
  • -g1
    按第一个字段分组
  • 最大2最小3
    第二个字段的最大值和第三个字段的最小值
  • 如果输入文件包含标题行,请在
选项中使用
--header忽略它

使用POSIX awk,您可以执行以下操作:

awk ' BEGIN{fmt="%-15s%-10s%-10s\n"; printf fmt,"School","max","min"}
      !($1 in sch) {idx[++i]=$1; sch[$1]; arr[$1,"min"]=100}
      $2>arr[$1,"max"]{arr[$1,"max"]=$2}
      $3<arr[$1,"min"]{arr[$1,"min"]=$3}
      END{for (e=1;e<=length(idx);e++) printf fmt,idx[e],arr[idx[e],"max"],arr[idx[e],"min"]}' file
School         max       min       
schoolA        99        48        
schoolB        94        36      
awk'BEGIN{fmt=“%-15s%-10s%-10s\n”;printf fmt,“School”,“max”,“min”}
!(sch中的$1){idx[++i]=1;sch[$1];arr[$1,“min”]=100}
$2>arr[$1,“max”]{arr[$1,“max”]=$2}

$3使用POSIX awk,您可以:

awk ' BEGIN{fmt="%-15s%-10s%-10s\n"; printf fmt,"School","max","min"}
      !($1 in sch) {idx[++i]=$1; sch[$1]; arr[$1,"min"]=100}
      $2>arr[$1,"max"]{arr[$1,"max"]=$2}
      $3<arr[$1,"min"]{arr[$1,"min"]=$3}
      END{for (e=1;e<=length(idx);e++) printf fmt,idx[e],arr[idx[e],"max"],arr[idx[e],"min"]}' file
School         max       min       
schoolA        99        48        
schoolB        94        36      
awk'BEGIN{fmt=“%-15s%-10s%-10s\n”;printf fmt,“School”,“max”,“min”}
!(sch中的$1){idx[++i]=1;sch[$1];arr[$1,“min”]=100}
$2>arr[$1,“max”]{arr[$1,“max”]=$2}

$3
getline
获取下一个输入行。但是,从
BEGIN
块执行此操作有点不雅观,因为Awk无论如何都会读取每一行。我会这样做:

NR==1{min=$3;max=$2;next} 
确保脚本启动时,将
max
min
初始化为第一行的值


($3
getline
获取下一个输入行。但是从
BEGIN
块执行此操作有点不雅观,因为Awk无论如何都会读取每一行。我会这样做:

NR==1{min=$3;max=$2;next} 
确保脚本启动时,将
max
min
初始化为第一行的值


($3with
sed 1d
可能更容易删除标题。@karakfa是的,它更短:)此外,我刚刚检查了手册页,发现datamash本身有内置选项……我不知道。现在我知道了,谢谢!with
sed 1d
可能更容易删除标题。@karakfa是的,它更短:)还有,我刚刚检查了手册页,发现datamash本身有一个内置选项……我不知道。现在我知道了,谢谢你!哇,谢谢你!我试过了,成功了!!你能告诉我“$1 in min{…”是什么意思吗?@Charlie-这是一个条件。它的计算结果为“true”如果当前记录中的第一个字段作为索引存在于
min
数组中。因此,如果
min
数组已经给定了初始变量,则会对遵循该条件的代码块进行评估,并且该代码块以
next
结束,这意味着如果条件为ition不匹配。
(3>5?a=1:”)
的计算结果为
,这是一个有效但不明确的no-op。因此它显示“如果3大于5,则为
a指定一个新值;否则,什么也不做。”ghoti和triplee很抱歉回复晚…感谢您的解释!哇,谢谢!我尝试过了,并且成功了!!您能告诉我是什么吗“$1在min{…”中的意思是?@Charlie-这是一个条件。它的计算结果为“真”"如果当前记录中的第一个字段作为索引存在于
min
数组中。因此,如果
min
数组已经给定了初始变量,则会对遵循该条件的代码块进行评估,并且该代码块以
next
结束,这意味着如果条件为不匹配。
(3>5?a=1:”)
的计算结果为
,这是一个有效但不明确的no-op。因此它显示“如果3大于5,则为
a指定一个新值;否则,不执行任何操作。”ghoti和triplee很抱歉迟了回复…谢谢你的解释!谢谢你的详细回复!但这对我来说有点太复杂了,我想我会使用Kent或datamash的第一个解决方案。谢谢你的详细回复!但这对我来说有点太复杂了,我想我会使用Kent或datamash的第一个解决方案。谢谢一个问题可以由许多人来解决