Awk查找每个键的最大值和最小值
我的数据如下所示: A学校和B学校每个班级的最高和最低期中成绩(未显示班级) 我想像这样合并它: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}
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}
$3getline
获取下一个输入行。但是,从BEGIN
块执行此操作有点不雅观,因为Awk无论如何都会读取每一行。我会这样做:
NR==1{min=$3;max=$2;next}
确保脚本启动时,将max
和min
初始化为第一行的值
($3getline
获取下一个输入行。但是从BEGIN
块执行此操作有点不雅观,因为Awk无论如何都会读取每一行。我会这样做:
NR==1{min=$3;max=$2;next}
确保脚本启动时,将max
和min
初始化为第一行的值
($3withsed 1d
可能更容易删除标题。@karakfa是的,它更短:)此外,我刚刚检查了手册页,发现datamash本身有内置选项……我不知道。现在我知道了,谢谢!withsed 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的第一个解决方案。谢谢一个问题可以由许多人来解决