2014-03-13 16 views
1

我告訴朋友,我會幫他完成作業,並且咬掉的東西超過了我的咀嚼量。我的技能真的很塵。在bash中用選項卡分隔符對文件進行排序並添加列

我有一個文本文件,行任意數量的,3列

Lap1 Lap2 Lap3 
33.2 33.0 31.9 
33.1 32.1 30.9 
34.1 33.8 33.7 
... 

而且我想通過該列中添加平均列,和排序。

我想我可以在原始文件CP到我的newLapTimes.txt,然後通過

total=$(awk { if (NR!=1) { print $1+$2+$3 }}) lapTimes.txt 
rows=$(awk {print NR} lapTimes.txt) 
average=$(expr $total/$rows) 

獲得平均,並添加到每一行的末尾我複製newLapTimes.txt

然後我只是sort -nk4 newLapTimes.txt -o newLapTimes.txt

但這看起來真的不合適,如果它甚至是正確的。

我希望這個答案是一個乾淨的方法腳本,而不是簡單的單線程。

+0

有可能是一個更好的方法來做到這一點,但我會用awk來計算平均值,然後對它進行排序。基本上如果文件是合理的,你可以使用awk將它在內存中排序。 –

回答

2

這是一種天真的方法,可以在外部排序。

$ { echo "Lap1 Lap2 Lap3 Average"; awk -v OFMT='%.1f' 'NR>1{print $1, $2, $3, ($1+$2+$3)/3}' input.txt | sort -k 4n,4; } > output.txt 
$ cat output.txt 
Lap1 Lap2 Lap3 Average 
33.1 32.1 30.9 32.0 
33.2 33.0 31.9 32.7 
34.1 33.8 33.7 33.9 

編輯:下面是一個使用bc計算浮動平均「bash」的版本。如果你根本不需要浮點運算(甚至不是平均值),那麼你可以使用註釋行來改變格式化字符串以使用整數(%d)。

#!/bin/bash 

printf "Lap1\tLap2\tLap3\tAverage\n" 
{ 
     while read x y z; do 
       #((average = (x + y + z)/3)) 
       average=$(bc <<< "scale=2; ($x + $y + $z)/3" 2>/dev/null) 
       printf "%.1f\t%.1f\t%.1f\t%.1f\n" "${x}" "${y}" "${z}" "${average}" 
     done < <(tail -n +2 input.txt) 
} | sort -k 4n,4 

$ ./t.sh 
Lap1 Lap2 Lap3 Average 
33.1 32.1 30.9 32.0 
33.2 33.0 31.9 32.7 
34.1 33.8 33.7 33.9 
+0

太棒了。我希望有一點更緊湊和awk可靠,但它似乎應該工作。 – user

+0

@user'bash'本身不會執行浮點運算,因此任何「本機」shell解決方案都將依賴於外部工具並且更加冗長(並且更慢)。你可以在'awk'中完成*整個*的東西,但可能不需要,而且這很容易讀取。 –

+0

那麼我的上面的例子只是一個泛化,幸運的是我正在使用的實際數據都是整數,但感謝知識。 – user

相關問題