2015-10-13 21 views
1

我想找到每列的中位數,但它不能像我想要的那樣工作。閱讀列和查找中位數(Bash)

1 2 3 
3 2 1 
2 1 5 

我期待爲

2 2 3 

的結果,但原來它只是給和錯誤和一些列的「總和」。以下是「列中位數」

while read -r line; do 
    read -a array <<< "$line" 
    for i in "${!array[@]}" 
    do 
     column[${i}]=${array[$i]} 
     ((length[${i}]++)) 
     result=${column[*]} | sort -n 
    done < file 
for i in ${!column[@]} 
do 
    #some median calculation..... 

注碼的一個片斷:我想練習bash的,這就是爲什麼我使用bash硬編碼。 我真的很感激,如果有人能幫助我,尤其是在BASH。謝謝。

+0

你能粘貼整個腳本和輸出。 – grimsock

回答

3

Bash是真的不適合這樣的低級文本處理:read命令執行系統調用的每個字符它的內容,這意味着它很慢,這是一個CPU豬。處理交互式輸入是可以的,但將其用於一般文本處理是瘋狂的。爲此,使用awk(Python,Perl等)會好得多。

作爲學習Bash的一個練習,我想猜想沒關係,但是請儘量避免在實際程序中使用read進行批量文本處理。欲瞭解更多信息,請參閱Novell & Linux Stack Exchange站點上的Why is using a shell loop to process text considered bad practice?,特別是 StéphaneChazelas(Shellshock Bash bug的發現者)所寫的答案。

無論如何,回到你的問題... :)

大部分代碼是好的,但

result=${column[*]} | sort -n 

不會做你希望它是什麼。

這裏有一種方法來獲取列位數純擊:

#!/usr/bin/env bash 

# Find medians of columns of numeric data 
# See http://stackoverflow.com/q/33095764/4014959 
# Written by PM 2Ring 2015.10.13 

fname=$1 
echo "input data:" 
cat "$fname" 
echo 

#Read rows, saving into columns 
numrows=1 
while read -r -a array; do 
    ((numrows++)) 
    for i in "${!array[@]}"; do 
     #Separate column items with a newline 
     column[i]+="${array[i]}"$'\n' 
    done 
done < "$fname" 

#Calculate line number of middle value; which must be 1-based to use as `head` 
#argument, and must compensate for extra newline added by 'here' string, `<<<` 
midrow=$((1+numrows/2)) 
echo "midrow: $midrow" 

#Get median of each column 
result='' 
for i in "${!column[@]}"; do 
    median=$(sort -n <<<"${column[i]}" | head -n "$midrow" | tail -n 1) 
    result+="$median " 
done 

echo "result: $result" 

輸出

input data: 
1 2 3 
3 2 1 
2 1 5 

midrow: 3 
result: 2 2 3 
+0

謝謝!我知道我現在犯的錯誤在哪裏。 – coava