如何平均不同文件的值并将其保存在新文件中

时间:2019-05-25 17:16:47

标签: shell awk

我大约有140个文件,这些文件包含我想使用脚本处理的数据。

文件有两种类型的名称:

  1. sys-time-4-16-80-15-1-1.txt

  2. known-ratio-4-16-80-15-1-1.txt

后两个数字不同。倒数第二个数字取1、50、100、150,...,300,最后一个数字的范围为1,2,3,4,5 ...,10。这些文件的示例位于此link中。

我想编写一个3列的新文件,如下所示:

第一列,文件的倒数第二个数字,即1,25,50 ... 第二列,每个sys-time-..文件中第二列的平均值。 第三列,每个known-ratio-..文件中第二列的平均值。

对于2nd columnssys文件的平均每对known,结果可能都有一行:

1    mean-sys-1 mean-know-1
1    mean-sys-2 mean-know-2
.
.
1    mean-sys-10 mean-know-10
50   mean-sys-1  mean-know-1
50   mean-sys-2  mean-know-2
.
.
50   mean-sys-10 mean-know-10
100  mean-sys-1  mean-know-1
100  mean-sys-2  mean-know-2
.
.
100  mean-sys-10 mean-know-10
....
....
300  mean-sys-10 mean-know-10

其中每一行对应于sysknown文件,文件的最后两个数字相同。 此外,我想在第一栏中复制倒数第二个文件。

我知道如何使用awk计算文件第二列的平均值:

awk '{ sum += $2; n++ } END { if (n > 0) print sum / n; }' sys-time-4-16-80-15-1-5.txt

但是我不知道如何遍历所有文件并使用上述三列构建结果文件。

2 个答案:

答案 0 :(得分:1)

我使用GNU Awk进行简单的按文件操作。这是未经测试的;请让我知道它如何运行。您可能需要查看printf()以获得漂亮的输出结果。

mapfile -t Files < <(find . -type f -name "*-4-16-80-15-*" |sort -t\- -k7,7 -k8,8)  #1
gawk '
  BEGINFILE {n=split(FILENAME, f, "-"); type=f[1]; a[type]=0}                    #2
            {a[type] = ($2 + a[type] * c++) / c}                                 #3
  ENDFILE   {if(type=="sys") print f[n], a[sys], a[known]}                       #4
' "${Files[@]}"
  1. 创建一个Bash数组,其中包含按最后两个“键”排序的匹配文件。稍后我们将把这个数组提供给Awk。请注意,在此示例中,我们如何在“ sys”文件和“已知”文件之间进行交替:
./known-ratio-4-16-80-15-2-150
./sys-time-4-16-80-15-2-150
./known-ratio-4-16-80-15-3-1
./sys-time-4-16-80-15-3-1
./known-ratio-4-16-80-15-3-50
./sys-time-4-16-80-15-3-50
  1. 在每个文件的开头,清除所有现有的平均值,并将类型保存为“ sys”或“ known”。

  2. 在每一行上,计算Cumulative Moving Average

  3. 在每个文件的末尾,检查文件类型。如果我们只处理了“ sys”文件,请打印文件名的最后一部分,然后打印平均值。

答案 1 :(得分:1)

这是一个使用GNU datamash来计算平均值的shell脚本(尽管您可以根据需要轻松地换成awk;我更喜欢使用datamash来计算统计信息):

#!/bin/sh

nums=$(mktemp)
sysmeans=$(mktemp)
knownmeans=$(mktemp)

for systime in sys-time-*.txt
do
    knownratio=$(echo -n "$systime" | sed -e 's/sys-time/known-ratio/')
    echo "$systime" | sed -E 's/.*-([0-9]+)-[0-9]+\.txt/\1/' >> "$nums"
    datamash -W mean 2 < "$systime" >> "$sysmeans"
    datamash -W mean 2 < "$knownratio" >> "$knownmeans"
done

paste "$nums" "$sysmeans" "$knownmeans"
rm -f "$nums" "$sysmeans" "$knownmeans"

它将创建三个临时文件,每列一个,并在使用每对文件中的数据填充它们之后,每行中的每一对,使用paste将它们组合在一起并将结果打印到标准输出中