对文件的一列进行平均

对文件的一列进行平均

我有一个 CSV 文件(带有时间戳数据),并且有一个脚本可以将一年中的每个月分解为一个单独的文件。该脚本将获取该月的数据并将其平均为单个值。部分代码如下;所有其他月份将与一月份的第一个月份相同。该代码将根据第 9 列将一年长的文件分成几个月(月份编号为 1-12),并将打印所有 17 个字段。下一个代码行是查看第 13 列并对文件中的所有数据求平均值(忽略所有缺失数据,指定为 -999),并将列平均值打印到新的 $i.monthlyavg 文件中。

awk -F ',' '$9= 1 {print $0}' $i > Jan.tmp
awk 'NR > 1 { for i = 13) if ($i != -999) {sum[i] += $i; num[i]++}
END { for (i = 13) print i, sum[i], num[i], sum[i]/num[i] }' Jan.tmp > $i.monthlyavg

我收到以下错误消息......

awk: cmd. line:1: NR > 1 { for i = 13) if (01-073-1003-SO2-1998.dat.out != -999) {sum[i] += 01-073-1003-SO2-1998.dat.out; num[i]++}
awk: cmd. line:1:              ^ syntax error
awk: cmd. line:1: NR > 1 { for i = 13) if (01-073-1003-SO2-1998.dat.out != -999) {sum[i] += 01-073-1003-SO2-1998.dat.out; num[i]++}
awk: cmd. line:1:                    ^ syntax error
awk: cmd. line:1: NR > 1 { for i = 13) if (01-073-1003-SO2-1998.dat.out != -999) {sum[i] += 01-073-1003-SO2-1998.dat.out; num[i]++}
awk: cmd. line:1:                                                  ^ syntax error
awk: cmd. line:1: NR > 1 { for i = 13) if (01-073-1003-SO2-1998.dat.out != -999) {sum[i] += 01-073-1003-SO2-1998.dat.out; num[i]++}
awk: cmd. line:1:                                                              ^ syntax error
awk: cmd. line:1: NR > 1 { for i = 13) if (01-073-1003-SO2-1998.dat.out != -999) {sum[i] += 01-073-1003-SO2-1998.dat.out; num[i]++}
awk: cmd. line:1:                                                                                                   ^ syntax error

 END { for (i = 13) print i, sum[i], num[i], sum[i]/num[i] }
awk: cmd. line:2:       ^ syntax error
awk: cmd. line:2:       END { for (i = 13) print i, sum[i], num[i], sum[i]/num[i] }
awk: cmd. line:2:                        ^ syntax error
awk: cmd. line:2:       END { for (i = 13) print i, sum[i], num[i], sum[i]/num[i] }
awk: cmd. line:2:                                                                  ^ unexpected newline or end of string

问题是什么?

答案1

如果您想对第 9 列中每个单独值的第 13 列中的数字进行平均,则无需为第 9 列中的每个值创建单独的文件。只需跟踪单独的总和并在最后将它们全部输出即可。

awk -F, '
    $13 != -999 { s[$9] += $13; n[$9]++ }
    END { for (i in s) print i, s[i]/n[i] }' some-file

您的代码的主要问题是您编写循环的方式存在语法错误for。根本for不需要循环,因为我们只访问第 13 列。


循环for有两种风格awk。您有“算术for循环”,这就是您可能想要使用的。它通常从一些初始化开始使用计数器进行迭代,直到不再进行某些逻辑测试。真的,有一些更新:

for (initialization; logical-test; update) statement

例如

for (i = 1; i <= NF; ++i) print i

另一种类型是我在上面的答案中显示的类型,它用于迭代数组的索引。请注意,循环可能不会以任何特定顺序迭代索引。

for (index-variable in array) statement

例如

for (key in data) print key, data[key]

答案2

for (i = 13)根本不是一个有效的 awk 结构。 (我真的需要告诉你这for i = 13) 在语法上根本不有效吗?)该for语句有两个版本:

  • for (expr1; expr2; expr3) statement
  • for (var in array) statement

您似乎正在尝试使用第一个 ( )。如果您想查看所有 17 个字段,您可以使用, 或者,更好的是,。如果您只想处理字段 #13 但保留循环结构,您可以使用.但是,如果您想要简单、直接的代码来完成这项特定的工作,您可以使用for (expr1expr2expr3statementfor (i = 1; i <= 17; i++)for (i = 1; i <= NF; i++)for (i = 13; i <= 13; i++)

  • i = 13; if ($i != -999) {sum[i] += $i; num[i]++},
  • if ($13 != -999) {sum[13] += $13; num[13]++}, 或者
  • if ($13 != -999) {sum += $13; num++}

…因为如果您只处理一列,则不需要数组。

而且,正如“他们”评论的那样,看起来非常非常就像你在双引号中运行 awk 一样。一切正常很多很多如果使用单引号会更好。

相关内容