对于冗长的问题感到抱歉,这归结为一个非常简单的问题 假设有n个文本文件,每个文件包含一列字符串(命名组)和一个整数(表示这些组中实例的值):
# filename xxyz.log
a 5
a 6
b 10
b 15
c 101
c 100
#filename xyzz.log
a 3
a 5
c 116
c 128
请注意,虽然任何给定文件中的两列的长度始终相同,但它们在文件之间有所不同。此外,并非所有文件都包含相同范围的组(第一组包含组a,b,c,而第二组仅包含组a和c)。在awk中,可以分别计算每个文件中第1列中每个字符串的第2列的平均值,并使用以下代码输出结果:
NAMES=$(ls|grep .log|awk -F'.' '{print $1}');
for q in $NAMES;
do
gawk -F' ' -v y=$q 'BEGIN {print "param", y}
{sum1[$1] += $2; N[$1]++}
END {for (key in sum1) {
avg1 = sum1[key] / N[key];
printf "%s %f\n", key, avg1;
} }' $q.log | sort > $q.mean;
done;
Howerver,由于上述原因,生成的.mean文件的长度因文件而异。对于每个.log文件,我想输出一个.mean文件,列出第一列中的整个组(ad)和相应的平均值或第二列中的空白空间,具体取决于该类别是否存在于。日志文件。我已经尝试了以下代码(为简洁而没有$ NAMES给出):
awk 'BEGIN{arr[a]="a"; arr[b]="b"; arr[c]="c"; arr[d]="d"}
{sum[$1] += $2; N[$1]++}
END {for (i in arr) {
if (i in sum) {
avg = sum[i] / N[i];
printf "%s %f\n" i, avg;}
else {
printf "%s %s\n" i, "";}
}}' xxyz.log > xxyz.mean;
但它返回以下错误:
awk: (FILENAME=myfile FNR=7) fatal: not enough arguments to satisfy format string
`%s %s
'
^ ran out for this one
任何建议都将受到高度赞赏。
答案 0 :(得分:2)
您是否在日志文件中有明确的零或负数?我不会假设。
第二个脚本的第一行不能达到你想要的效果:
awk 'BEGIN{arr[a]="a"; arr[b]="b"; arr[c]="c"; arr[d]="d"}
这会将"a"
分配给arr[0]
(因为a
是以前未使用过的变量),然后"b"
分配到同一元素(因为b
是之前未使用的变量),然后是"c"
,然后是"d"
。显然,不是你想到的。只要您知道只有四个组,这个(未经测试的)代码就可以完成您需要的工作。如果你不熟悉这些组,你需要一个更复杂的程序(它可以完成,但更难)。
awk 'BEGIN { sum["a"] = 0; sum["b"] = 0; sum["c"] = 0; sum["d"] = 0 }
{ sum[$1] += $2; N[$1]++ }
END { for (i in sum) {
if (N[i] == 0) N[i] = 1 # Divide by zero protection
avg = sum[i] / N[i];
printf "%s %f\n" i, avg;
}
}' xxyz.log > xxyz.mean;
这将为缺失的组打印零平均值。如果您愿意,可以这样做:
awk 'BEGIN { sum["a"] = 0; sum["b"] = 0; sum["c"] = 0; sum["d"] = 0 }
{ sum[$1] += $2; N[$1]++ }
END { for (i in sum) {
if (N[i] == 0)
printf("%s\n", i;
else {
avg = sum[i] / N[i];
printf "%s %f\n" i, avg;
}
}
}' xxyz.log > xxyz.mean;
答案 1 :(得分:1)
对于每个.log文件,我想输出一个列出整个文件的.mean文件 第一列中的组(a-d)范围和相应的平均值 第二列中的值或空格取决于是否这样 类别存在于.log文件中。
不仅仅是一个awk解决方案,但你可以通过它获得所有组。
awk '{print $1}' *.log | sort -u > groups
计算均值后,您可以加入群组文件。假设您的第二个输入文件的方法看起来像这个临时的中间文件。 (我称之为xyzz.tmp。)
a 4
c 122
加入群组,保留群组文件中的所有值。
$ join -a1 groups xyzz.tmp > xyzz.mean
$ cat xyzz.mean
a 4
b
c 122
答案 2 :(得分:1)
这是我对这个问题的看法。像:
一样运行./script.sh
script.sh
的内容:
array=($(awk '!a[$1]++ { print $1 }' *.log))
readarray -t sorted < <(for i in "${array[@]}"; do echo "$i"; done | sort)
for i in *.log; do
for j in "${sorted[@]}"; do
awk -v var=$j '
{
sum[$1]+=$2
cnt[$1]++
}
END {
print var, (var in cnt ? sum[var]/cnt[var] : "")
}
' "$i" >> "${i/.log/.main}"
done
done
grep . *.main
的结果:
xxyz.main:a 5.5
xxyz.main:b 12.5
xxyz.main:c 100.5
xyzz.main:a 4
xyzz.main:b
xyzz.main:c 122
答案 3 :(得分:0)
这是一个纯粹的awk答案:
find . -maxdepth 1 -name "*.log" -print0 |
xargs -0 awk '{SUBSEP=" ";sum[FILENAME,$1]+=$2;cnt[FILENAME,$1]+=1;next}
END{for(i in sum)print i, sum[i], cnt[i], sum[i]/cnt[i]}'
很容易将其推入文件 -