Linux

從文件中輸出多個組線的平均值的腳本

  • November 30, 2015

這是我試圖從中提取資訊的文件 car_sales.txt 的“小”部分(完整文件有大約 700 行,車輛品牌比這裡列出的要多):

first_name,last_name,price_paid,brand,year Mann,Mathers,20500.79,Chevy,2012 Doug,Samual,21000.12,Dodge,2015 Walter,Gray,17000.87,Dodge,2010 Jessica,Garnet,17350.00,MINI,2009 Paula,Raymond,45300.87,BMW,2015 Willie,Reynolds,64950.05,BMW,2015 Sam,Collins,70200.35,Lexus,2014 Katy,Martinez,29580.84,Chevy,2012 Nicole,Davis,31650.60,Chevy,2009 Brenda,Gray,12400.56,Dodge,2012 Samantha,Fernandez,27900.21,MINI,2015 Eric,Woods,68900.85,BMW,2009 George,Luke,33453.91,BMW,2011 Mildred,Takey,46820.80,Lexus,2012

我想輸出“品牌”和“價格支付”列(並找到每個品牌支付的所有汽車的平均價格),排序(az),第一行“標題”被刪除。這是我正在尋找的輸出(來自上面列出的範例):

BMW,53151.4 Chevy,27244.1 Dodge,16800.5 Lexus,58510.6 MINI,22625.1

現在我一直在努力解決這個問題兩天沒有運氣(我是新手),我能想出的最好的是:

sed '1d' car_sales.txt |awk -F ',' '/Chevy/{print $3}' $1|awk '{total += $1; count ++}END{print "Chevy," total/count}'

現在很明顯,這不是我要找的“不是”;如果我只需要“一個”​​品牌/Price_Paid 的平均輸出,那麼它會起作用,我只需輸入我正在尋找的單個“模式”,然後我就會得到支付的平均價格。

但是,我正在尋找一種方法來擷取並輸出 car_sales.txt 文件中為所有品牌支付的平均價格。除了我列出的部分中的 5 個(大約 50 多個品牌)之外,還有更多品牌。

我已經閱讀了我擁有的 3 本書,並在網上掃描了幾個小時,而對於我的一生,我無法弄清楚。也許我什至沒有找對地方,我認為 awk 會是答案,但它是如此龐大。非常感謝您提前提供的幫助。

然後我有了一個想法,認為我已經找到了實現它的方法,並開始編寫這個腳本。從邏輯上講,它似乎在我腦海中起作用,我的想法是我會使用第一個函式的輸出作為第二個函式的輸出。唉,這也不起作用,我以為我在正確的軌道上,但沒有。

#!/bin/bash

#This will output the car "brand"
function brand {
       sed '1d' $1| cut -d ',' -f 4 |sort|uniq 
}

#The output of function "brand", will be the pattern for function "average"
function average {
   awk -F ',' '/'"$names"'/{print $3}' $1|awk '{total += $1; count ++}END{print "'$names'" "," total/count}'

}

brand $1
names=$(brand)
average $1 $names

由於awk數組是按字元串索引的,因此您可以使用一個數組來保存該品牌到目前為止的總價格,並使用另一個數組來保存該品牌的記錄數。

因為“品牌”是欄位 4,所以您可以像這樣索引數組awk

total_price[$4] += $3        # accumulate total price for this brand
count[$4] += 1               # increment count of records for this brand

最後,遍歷數組的鍵,並在計算平均值時格式化輸出。

由於 POSIXawk不包含排序功能,因此將awk命令的輸出通過管道傳輸到標準的 Unixsort命令。

請試試這個:

腳本

#!/bin/sh

#first_name,last_name,price_paid,brand,year
#print for each brand, the average price paid

awk -F, '
   NR == 1 {
       next                        # skip header
   }
   {
       price_paid[$4] += $3        # accumulate total price for this brand       
       count[$4] += 1              # increment count of records for this brand
   }
   END {
       for (brand in price_paid) {
           printf "%s,%7.2f\n", brand, price_paid[brand] / count[brand]
       }
   }
' < "${1:?filename required}" | sort

註釋/解釋

  1. 呼叫awk命令,將欄位分隔符設置為逗號 ( ,) 並在此行的單引號和下面幾行的下一個單引號之間傳遞所有內容,作為腳本:
awk -F, '
  1. Skip Header:如果目前記錄號為1,則跳過目前行(第一行)的所有處理,獲取下一行輸入:
   NR == 1 {
       next                        # skip header
   }
  1. Accumulate Price Total Per Brand(在每一行上執行):

數組price_paid並由字元串count索引。 將目前支付的價格 ( ) 添加到該品牌的 price_paid 總額中。 增加此品牌的記錄數: brand
$3

   {
       price_paid[$4] += $3        # accumulate total price for this brand    
       count[$4] += 1              # increment count of records for this brand
   }
  1. 列印輸出表:處理完所有輸入後,通過鍵 ( brand) 單步執行price_paid數組,並為每個brand列印 的和brand平均值price_paidbrand
   END {
       for (brand in price_paid) {
           printf "%s,%7.2f\n", brand, price_paid[brand] / count[brand]
       }
  }
  1. 終止腳本參數,從文件名參數重定向輸入,並將命令的輸出通過管道awk傳遞給sort命令:
' < "${1:?filename required}" | sort

單引號 ( ') 將腳本參數終止為awk.

< "${1:?filename required}"將標準輸入awk從第一個命令行參數指定的文件名重定向到腳本。如果沒有參數,則 shell 將列印一條包含“需要文件名”的錯誤消息並以錯誤狀態退出。

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