從文件中輸出多個組線的平均值的腳本
這是我試圖從中提取資訊的文件 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
最後,遍歷數組的鍵,並在計算平均值時格式化輸出。
由於 POSIX
awk
不包含排序功能,因此將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
註釋/解釋
- 呼叫
awk
命令,將欄位分隔符設置為逗號 (,
) 並在此行的單引號和下面幾行的下一個單引號之間傳遞所有內容,作為腳本:awk -F, '
- Skip Header:如果目前記錄號為1,則跳過目前行(第一行)的所有處理,獲取下一行輸入:
NR == 1 { next # skip header }
- 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 }
- 列印輸出表:處理完所有輸入後,通過鍵 (
brand
) 單步執行price_paid
數組,並為每個brand
列印 的和brand
平均值price_paid
:brand
END { for (brand in price_paid) { printf "%s,%7.2f\n", brand, price_paid[brand] / count[brand] } }
- 終止腳本參數,從文件名參數重定向輸入,並將命令的輸出通過管道
awk
傳遞給sort
命令:' < "${1:?filename required}" | sort
單引號 (
'
) 將腳本參數終止為awk
.
< "${1:?filename required}"
將標準輸入awk
從第一個命令行參數指定的文件名重定向到腳本。如果沒有參數,則 shell 將列印一條包含“需要文件名”的錯誤消息並以錯誤狀態退出。