循環遍歷特定模式旁的目錄和總和值,產生平均值

循環遍歷特定模式旁的目錄和總和值,產生平均值

我想循環遍歷目錄中的所有檔案。

文件的設定如下:

<Overall>4
other data
<Overall>2
other data
......

我有代碼:

for file in .dat; 
do
awk 'x+=sub(/<Overall>/,""){y+=$0} END{print FILENAME, y/x}' $file
done

這會列印出檔案中值的平均值,但是我想要的是將腳本所在的目錄作為參數,並對目錄中的所有 .dat 檔案執行 awk 命令。

我嘗試過使用代碼:

for file in $1

但出現錯誤:

awk: cmd. line:1: fatal cannot open file `folder' for reading (No such file or directory)

除此之外,我還希望能夠將平均值的輸出從高到低排序。

答案1

兩種變體:

  1. 循環文件並awk為每個文件調用一次,或者
  2. 為腳本提供awk所有文件,讓它計算每個文件的平均值並在運行過程中進行報告。

對以下任何解決方案的結果進行排序可以透過將其輸出通過管道來完成

sort -k2,2rn

這對第二個欄位(平均值)進行反向數字排序。


第一個解決方案:

#!/bin/sh

for name in "$1"/*.dat; do
    test -f "$name" || continue   # skip non-files
    awk -F '>' '/<Overall>/ { s+=$NF; n++ } END { print FILENAME, s/n }' "$name"
done

該腳本需要命令列上的目錄名稱作為第一個也是唯一一個命令列參數。該awk腳本將查找包含字串 的所有行,並對該行上後的值Overall求和(在 中)。最後,平均值與檔案名稱一起輸出。該變數保存我們在 中加入內容的次數。s>ns


第二種解決方案(需要 GNU Awk):

#!/bin/sh

find "$1" -maxdepth 1 -type f -name '*.dat' \
    -exec awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' {} +

該腳本與第一個腳本一樣,需要一個目錄名稱作為其唯一的命令列參數。它用於一次find執行awk包含盡可能多的文件的腳本。.dat

awk腳本利用 GNU Awk 的ENDFILE觸發器來輸出計算值,並在處理每個檔案後、開始讀取下一個檔案之前重設s和變數。n

這也可以寫成

#!/bin/sh

awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' "$1"/*.dat

但這依賴於"$1"/*.dat不要擴展到太長的文件名清單(這也要求每個.dat名稱都是常規文件,這是上面find命令所保證的-type f)。

相關內容