You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决Bash中grep报错并实现首两列重复行的平均值计算

问题描述

数据集

15.0  -100.0  409.27  5.7103  0.0106  0.0062  652.04
15.0  -99.5  409.14  5.6868  0.0109  0.0065  652.02
15.0  -99.0  409.23  5.4866  0.0108  0.0063  651.47
15.0  -98.5  409.19  5.4588  0.0107  0.0063  651.34
15.0  -98.5  409.17  5.3488  0.0105  0.0062  651.30
15.0  -98.0  409.16  5.2951  0.0104  0.0061  651.24
15.0  -97.5  409.17  5.2647  0.0104  0.0061  651.22
15.0  -97.0  409.27  5.0288  0.0098  0.0056  650.60

需求

对比每行前两列,若两行前两列值相同,则计算其余5列的平均值并合并为一行;若不同则保留原行。

编写的Bash代码

sort -k 1 -n -k 2 -n file1 > temp
awk '{print $1, $2}' temp | uniq > file2
while read line
do
    n=`grep -c "$line" temp`
    #echo $n
    grep -E "$line" temp > temp1
        awk -v n=$n '{sum+=$3} END {print sum/n}' temp1 > val1;
        awk -v n=$n '{sum+=$4} END {print sum/n}' temp1 > val2;
        awk -v n=$n '{sum+=$5} END {print sum/n}' temp1 > val3;
        awk -v n=$n '{sum+=$6} END {print sum/n}' temp1 > val4;
        awk -v n=$n '{sum+=$7} END {print sum/n}' temp1 > val5;
     
     echo $line $val1 $val2 $val3 $val4 $val5 >> Averages.dat;
done < file2

报错信息

grep: invalid option -- '.'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.


问题解决

1. 修复grep报错

报错原因是$line包含以-开头的内容(比如-100.0),grep会将其识别为命令选项而非匹配字符串。可以通过两种方式解决:

  • 使用--分隔选项与匹配模式,明确告知grep后续内容是匹配字符串:
    n=$(grep -c -- "$line" temp)
    grep -F -- "$line" temp > temp1
    
  • 加上-F参数启用固定字符串匹配,避免正则解析的同时,配合--彻底避免选项混淆(此处无需正则匹配,固定匹配更高效)。

2. 修正变量赋值错误

原代码将awk结果输出到文件,echo $line $val1实际输出的是文件名而非文件内的平均值。需改用命令替换直接将结果赋值给变量:

val1=$(awk '{sum+=$3} END {print sum/NR}' temp1)
val2=$(awk '{sum+=$4} END {print sum/NR}' temp1)
val3=$(awk '{sum+=$5} END {print sum/NR}' temp1)
val4=$(awk '{sum+=$6} END {print sum/NR}' temp1)
val5=$(awk '{sum+=$7} END {print sum/NR}' temp1)

这里用NR(当前处理行数)替代传入的n,代码更简洁可靠。

3. 高效的纯awk替代方案

原bash循环多次调用grep和awk,效率极低。可以用awk一步完成排序、分组求平均的全部操作,无需临时文件:

awk '
    {
        key = $1 FS $2
        sum3[key] += $3
        sum4[key] += $4
        sum5[key] += $5
        sum6[key] += $6
        sum7[key] += $7
        count[key]++
    }
    END {
        PROCINFO["sorted_in"] = "@ind_num_asc"  # 按数字顺序排序结果
        for (k in count) {
            printf "%s %.4f %.4f %.4f %.4f %.4f\n", 
                k, 
                sum3[k]/count[k], 
                sum4[k]/count[k], 
                sum5[k]/count[k], 
                sum6[k]/count[k], 
                sum7[k]/count[k]
        }
    }
' file1 > Averages.dat

该脚本的作用:

  • 以前两列为分组键,累加各列总和与计数
  • 最后遍历所有分组,计算并输出平均值,同时按数字顺序排序
  • 用printf控制小数精度,避免输出冗余位数

内容的提问来源于stack exchange,提问作者Monika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 21:37:51