Bash脚本优化:单次执行获取比值的最大值与最小值
问题
我有一个bash脚本,输出包含时间戳、value1、value2以及value1/value2比值的表格,示例输出如下:
2022-08-07 21:00 2784000/8750=318 2022-08-07 20:00 2792000/8760=318 2022-08-07 19:00 2790000/8760=318 2022-08-07 18:00 2776000/8750=317 2022-08-07 17:00 2804000/8570=327 2022-08-07 16:00 2799000/8580=326 2022-08-07 15:00 2783000/8590=323 2022-08-07 14:00 2729000/8580=318 2022-08-07 13:00 2638000/8530=309 2022-08-07 12:00 2637000/8490=310 2022-08-07 11:00 2610000/8450=308 2022-08-07 10:00 2595000/8470=306 2022-08-07 09:00 2616000/8490=308 2022-08-07 08:00 2604000/8470=307 2022-08-07 07:00 2619000/8450=309 2022-08-07 06:00 2626000/8530=307 2022-08-07 05:00 2627000/8530=307 2022-08-07 04:00 2634000/8530=308 2022-08-07 03:00 2626000/8470=310 2022-08-07 02:00 2625000/8530=307 2022-08-07 01:00 2676000/8540=313 2022-08-07 00:00 2654000/8590=308 2022-08-06 23:00 2673000/8610=310 2022-08-06 22:00 2641000/8570=308 2022-08-06 21:00 2655000/8610=308 2022-08-06 20:00 2665000/8670=307 2022-08-06 19:00 2672000/8670=308 2022-08-06 18:00 2626000/8680=302 2022-08-06 17:00 2581000/8690=297 2022-08-06 16:00 2581000/8720=295 2022-08-06 15:00 2560000/8720=293
目前我通过./script.sh | cut -f2,2 -d= | sort -n按等号右侧的比值进行排序,想要将最大值和最小值分别赋值给变量。虽然可以通过取首尾行来实现,但这样需要执行两次script.sh,请问是否有更高效的方法无需重复执行脚本即可获取最大值和最小值?
解决方案
方法1:用awk一次性计算最值
直接用awk遍历脚本输出的每一行,提取等号后的比值,单遍扫描中跟踪最大值和最小值,最后赋值给变量:
read min_val max_val <<< $(./script.sh | awk -F= ' BEGIN { min = 1e18; max = -1e18 } { val = $2 + 0 # 转为数值类型 if (val < min) min = val if (val > max) max = val } END { print min, max } ') echo "最小值: $min_val" echo "最大值: $max_val"
这种方法只执行一次script.sh,效率最高。
方法2:排序后一次性提取首尾值
如果偏好使用sort,可以把排序结果暂存,同时获取首尾行,避免重复执行脚本:
# 方式1:用awk提取排序后的首尾行 read min_val max_val <<< $(./script.sh | cut -d= -f2 | sort -n | awk 'NR==1{min=$0} END{print min, $0}') # 方式2:把排序结果存入bash数组 sorted_vals=($(./script.sh | cut -d= -f2 | sort -n)) min_val=${sorted_vals[0]} max_val=${sorted_vals[-1]}
方法3:纯bash循环逐行处理
如果不想依赖awk或sort,可直接用bash循环实现:
min_val=999999 max_val=0 ./script.sh | while IFS='=' read -r rest val; do val=$((val)) if (( val < min_val )); then min_val=$val fi if (( val > max_val )); then max_val=$val fi done echo "最小值: $min_val" echo "最大值: $max_val"
注:若脚本输出量很大,这种纯bash循环的效率会低于awk。
内容的提问来源于stack exchange,提问作者linux_beginner
相关产品推荐
相关产品推荐

