我有以下程序,如果第四列第一行的值是最高的(与具有相同命名样式的其他 8 个文件相比),则允许我移动文件(实际上是表)。以下是脚本:
#! /bin/bash
river=mississippi
highest=1
for model in H08 MPI-HM WBM PCR-GLOBWB
do
for gcm in GFDL-ESM2M HadGEM2-ES IPSL-CM5A-LR MIROC-ESM-CHEM NorESM1-M
do
for scenario in hist rcp8p5 rcp4p5
do
RESULT=$(awk 'FNR==1 {print $4, FILENAME}' ${model}_${gcm}_${scenario}_${river}[1-9]/${model}_${gcm}_${scenario}_${river}[1-9].txt | sort -n -r| head -1)
highest="$(echo $RESULT | cut -d ' ' -f1 )"
hifile="$(echo $RESULT | cut -d ' ' -f2 )"
echo "highest was $highest in $hifile"
cp "$hifile" "/home/stevens/SUMARIO/Fred/highest_discharge/${river}/${model}_${gcm}_${scenario}_${river}.txt"
done
done
done
然后,我想以这样的方式调整此脚本,而不是复制具有最高值的文件(在第一行,第四列),我想复制在第四列具有最高平均值的文件,在与其他文件的比较。任何提示或建议将不胜感激!
答案1
只需更改计算结果的方式即可:
RESULT=$(awk '{x+=$4} END{print x/NR, FILENAME}' ${model}_${gcm}_${scenario}_${river}[1-9]/${model}_${gcm}_${scenario}_${river}[1-9].txt | sort -n -r| head -1)
上面的作用是:它将第四行中的所有值相加,并在最后打印结果除以行数。
因为它除以行数,所以如果文件中有空行,您将得到意想不到的结果:总和不会考虑这些,但除以行数。
编辑:
我在第一次尝试时遇到错误,导致脚本仅考虑最后一个文件的最大值(因为 END 是在全部文件已处理)
正确版本:
awk 'FNR==1 && NR>1 {print x/nr, file;x=0}{x+=$4; nr=FNR; file=FILENAME} END{print x/nr, file, x, nr}' ${model}_${gcm}_${scenario}_${river}[1-9]/${model}_${gcm}_${scenario}_${river}[1-9].txt | sort -n -r| head -1
解释:
- 我们每次打印以前的文件已解析。因为每次读取新文件时 FNR 都会重置,所以我们检查是否开始了一个新文件 (FNR == 1) 并且我们不在第一个文件 (NR > 1)。如果是这样,我们打印平均值和从前一个文件保存的文件名。我们还重置 x (我们保留平均值)
- 否则我们开始计算 x。我们还保存该文件中的记录数(FNR)和文件名
- 最后我们打印最后一个文件的平均值
答案2
看起来您已经弄清楚如何定位列本身。现在您需要做的就是获取所有 4 个文件的第四列的平均值,然后复制平均值最高的文件(只是重新陈述您已经说过的内容)。
基本上,您需要做的是将 4 个文件中每个文件的第 4 列的输出相加,然后除以第 4 列的行数以获得平均值。然后复制平均值最高的文件。
我想您只是想知道如何获得平均值,对吗?
echo "$file1_col4" | wc -l
通过执行类似或 之类的操作可以轻松获取行数wc -l <<< "$file1_col4"
,您应该已经拥有了。将每个值存储在一个变量中以便稍后除以。所以我们就这样说:
file1_col4_rows=$(echo "$file1_col4" | wc -l)
要获取该列的总计,您需要执行以下操作:
file1_col4_total=$(echo "$file1_col4" | awk '{total = total + $1}END{print total}')
您可以对所有 4 个文件执行此操作,然后除以之前设置为变量的列中的总行数。 Bash 有一个内置函数可以处理这个问题,但我更喜欢使用perl
:
file1_avg=$(perl -e "print $file1_col4_total/$file1_col4_rows")
通过对所有 4 个文件执行此操作,您可以通过引用变量轻松查看哪个文件具有最高的平均第 4 列$fileN_avg
,然后复制具有最高值的变量的文件:
file_to_copy="$(echo "file1 $file1_avg
file2 $file2_avg
file3 $file3_avg
file4 $file4_avg" |
sort -nrk2 |
head -1 |
awk '{print $1}')"
然后简单地cp "$file_to_copy" /path/where/it/belongs/