查找文件中的最大值和最小值,并打印该行

18

我有一个文件,第一列是数字。

100,red
101,blue
102,black

我应该编写一个shell脚本,它将打印具有最大和最小数字的行。
max=0
cat file.txt|while read LINE
do
    fir=`echo $LINE|awk '{print $2}'`
    sec=`echo $LINE|awk '{print $3}'`
    if [ $fir -gt $max ]; then
       max=$fir
    fi
    if [ $sec -gt $max ];then
        max=$sec
    fi
done

grep $max file.txt

这是我目前为止尝试寻找最大值的方法。


一种非常“昂贵”的解析行的方法,为什么你要看 ...awk '{print $3}' ... 你只有2个元素?@sudo_O是正确的,awk在这里是最好的选择,但如果你只是想学习shell编程,那么可以简化为 while read fir sec ; do if [ $fir .... done < file.txt。祝你好运。 - shellter
max 在由管道引起的子shell中被设置。只需更改为 while read LINE; do ...; done < file.txt。但正如其他人指出的那样,这非常昂贵。 - chepner
你应该写一个shell脚本吗?这是一种作业吗? - stephanmg
6个回答

37

最小值:

[bash]$ cut -f1 -d"," file_name | sort -n | head -1

求最大值:

[bash]$ cut -f1 -d"," file_name | sort -n | tail -1

这个解决方案是可行的,但排序比仅查找最小值更昂贵(O(n log n) vs O(log n))。有没有更有效的方法? - Vivek Subramanian
2
你好,你可以尝试这个命令:awk -v max=0 '{if($1>max){want=$2; max=$1}}END{print want} ' 文件名 - Ali Ait-Bachir

13

或者使用sort和sed命令

$ sort -n id | sed -n '1p;$p'
100 red
102 black

-n标志 - 按数字排序。

如何使用它:

$ a=($(sort -n id | sed -n '1s/^\([0-9]\+\).*$/\1/p;$s/^\([0-9]\+\).*$/\1/p'))
$ echo "min=${a[0]}, max=${a[1]}"
min=100, max=102

这是一个简单而优雅的解决方案! - BioCoder

6
如果您有 GNU awk,建议您完全使用 awk 处理此事:
$ awk -F, '{a[$1]=$0}END{asorti(a,b);print a[b[1]]"\n"a[b[NR]]}' file
100,red
102,black

如果您没有:
$ awk -F, 'NR==1{s=m=$1}{a[$1]=$0;m=($1>m)?$1:m;s=($1<s)?$1:s}END{print a[s]"\n"a[m]}' file
100,red
102,black

或者预先排序并打印第一行和最后一行:

$ sort -t',' -nk1 file | awk 'NR==1;END{print}'
100,red
102,black

谢谢,但我遇到了“未定义函数asorti”的错误,而且我想要打印整行,而不仅仅是数字。 - hackio
你使用的是什么系统?看起来你没有安装GNU awk。 - Chris Seymour
第二个很好用,但是很抱歉我忘记了在数字和颜色之间加逗号。 - hackio
我喜欢这些解决方案。脚本语言对于日常任务非常方便。我享受它们的可用性,以及测试和原型设计时最小的(代码)开销。 - stephanmg

3
[bash]$ cat log
100,red
101,blue
102,black
[bash]$ all=( $(sort log | cut -f1 -d',') )
[bash]$ echo "MIN: ${all[0]} and MAX: ${all[${#all[@]}-1]}"
MIN: 100 and MAX: 102

使用已排序的元素创建一个数组。第一个和最后一个元素包含最小值和最大值。


1
你想在第一个字段上按数字进行排序 sort -t',' -nk1 file - Chris Seymour

1

在zip CSV文件中

最小值

bzcat file.csv.bz2 | cut -f2 -d";" | sort -n | head -2

最大值

bzcat file.csv.bz2 | cut -f2 -d";" | sort -n | tail -1

祝好,

阿里


2
这与什么相关?OP(隐含地)表示他得到了一个纯文本文件。 - stephanmg

0
我认为这种方法也非常美丽,希望将来对某人有所帮助。假设你拥有这些数据:
$ cat file.txt
red,100
blue,101
black,90

现在使用GNU datamash

$ <file.txt datamash -t, -sg1 min 2

结果
black,90
blue,101
red,100

-t, 指定输入数据中的列以逗号分隔

-s:确保在执行任何计算之前,根据分组列对输入数据进行排序

-g1:根据第一列中的值对数据进行分组

min 2:对于第一列中的每个唯一值,计算第二列中的最小值


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接