Awk

awk 的數字格式和舍入問題

  • June 4, 2020

當我試圖找到一列值的平均值時,我想得到確切的數字。

例如,這是輸入值列:

1426044
1425486
1439480
1423677
1383676
1360088
1390745
1435123
1422970
1394461
1325896
1251248
1206005
1217057
1168298
1153022
1199310
1250162
1247917
1206836

當我使用以下命令時:

... | awk '{ sum+=$1} END { print sum/NR}'

我得到以下輸出:1.31638e+06. 但是,我想要這種格式的確切數字,1316375.05甚至更好 1,316,375.05

如何僅使用命令行工具來做到這一點?

編輯 1

我找到了以下單行 awk 命令,它將獲得最大值、最小值和平均值:

awk 'NR == 1 { max=$1; min=$1; sum=0 } { if ($1>max) max=$1; if ($1<min) min=$1; sum+=$1;} END {printf "Min: %d\tMax: %d\tAverage: %.2f\n", min, max, sum/NR}'

為什麼NR必須初始化為1?當我刪除NR == 1時,我得到了錯誤的結果。

編輯 2

我從Is there a way to get the min, max, median, and average of a numbers in a single command? 中找到了以下 awk 腳本?. 它將一次性獲得單列數字數據的總和、計數、平均值、中值、最大值和最小值。它從標準輸入讀取,並在一行上列印輸出的製表符分隔列。我稍微調整了一下。我注意到它不需要NR == 1與上面的 awk 命令不同(在我的第一次編輯中)。有人可以解釋為什麼嗎?我認為這與數字數據已被排序並放入數組的事實有關。

#!/bin/sh

sort -n | awk '

 $1 ~ /^(\-)?[0-9]*(\.[0-9]*)?$/ {
   a[c++] = $1;
   sum += $1;
 }
 END {
   ave = sum / c;
   if( (c % 2) == 1 ) {
     median = a[ int(c/2) ];
   } else {
     median = ( a[c/2] + a[c/2-1] ) / 2;
   }

   {printf "Sum: %d\tCount: %d\tAverage: %.2f\tMedian: %d\tMin: %d\tMax: %d\n", sum, c, ave, median, a[0], a[c-1]}
 }
'
... | awk '{ sum+=$1} END { print sum/NR}'

預設情況下,(GNU) awk 列印最多 6 個有效數字(加上指數部分)的數字。這來自變數OFMT預設值。它並沒有在文件中這麼說,但這僅適用於非整數值。

您可以更改OFMT以影響所有print語句,或者更確切地說,只是printf在此處使用,因此如果平均值恰好是整數,它也可以工作。類似的東西%.3f會列印小數點後三位數字。

...| awk '{ sum+=$1} END { printf "%.3f\n", sum/NR }'

請參閱文件以了解fandg和精度修飾符的含義(.prec在第二個連結中):

awk 'NR == 1 { max=$1; min=$1; sum=0 } ...'

這不會初始化NR. 相反,它檢查是否NR等於一,即我們在第一行。(==是比較,=是賦值。) 如果是,則初始化max和。沒有它,就會從零開始。你永遠不可能有一個負的最大值或一個正的最小值。min``sum``max``min

引用自:https://unix.stackexchange.com/questions/590138