2011-11-21 102 views
16

我得到以下輸出:猛砸關聯數組排序

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999 

哪個以下腳本的結果:

for k in "${!authors[@]}" 
do 
    echo $k ' - ' ${authors["$k"]} 
done 

所有我想要的是得到這樣的輸出:

Pushkin - 100500 
Dostoyevsky - 9999 
Gogol - 23 

這意味着在關聯數組的鍵應該由值進行排序。有沒有簡單的方法來做到這一點?

回答

17

您可以輕鬆地整理你的輸出,在降第3場的數值順序:

for k in "${!authors[@]}" 
do 
    echo $k ' - ' ${authors["$k"]} 
done | 
sort -rn -k3 

(1)更多關於sort命令見排序。這只是排序輸出線;我不知道有什麼方法直接在bash中對數組進行排序。

我也看不出上面可以給你的名字(「普希金」等)作爲數組鍵。在bash中,數組鍵總是整數。

+6

擊4.0增加關聯數組,其中鍵可以是字符串。 –

+2

好吧,我會......你說得對。它只需要'declare -A authors'。 –

+1

您的解決方案有效。據我瞭解,它只是排序輸出字符串,而不是關聯數組的內容,但無論如何,產生的輸出是我所需要的。 – Graf

7

另外,您可以索引排序,並通過數組使用索引的排序列表循環:

authors_indexes=(${!authors[@]}) 
IFS=$'\n' authors_sorted=($(echo -e "${authors_indexes[@]/%/\n}" | sed -r -e 's/^ *//' -e '/^$/d' | sort)) 

for k in "${authors_sorted[@]}"; do 
    echo $k ' - ' ${authors["$k"]} 
done 
+0

Boo,噓聲:'echo -e'。考慮'printf的「%s的\ n」「$ {authors_indexes [@]}」'擴展的陣列成多行的方式,不依賴於違反POSIX SH(不只是擴展的,但實際行爲:任何參數除了'-n'需要打印它的文本,除非它包含反斜槓或'-n'存在,在這種情況下,行爲完全是實現定義的)。或'printf的「%s的\ 0」「$ {數組[@]}」'展開數組作爲NUL-分隔字符串,因此,即使你有你的鑰匙文字換行(其中*是*法律,工程的方式)。 –

+0

......看到http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html,尤其是應用信息部分。 –

2

擴展從@AndrewSchulman答案,使用-rn作爲一個全球性的排序選項逆轉所有列。在本例中,具有相同關聯數組值的作者將按名稱的相反順序輸出。

例如

declare -A authors 
authors=([Pushkin]=10050 [Gogol]=23 [Dostoyevsky]=9999 [Tolstoy]=23) 

for k in "${!authors[@]}" 
do 
    echo $k ' - ' ${authors["$k"]} 
done | sort -rn -k3 

排序特定列將輸出

 
Pushkin - 10050 
Dostoyevsky - 9999 
Tolstoy - 23 
Gogol - 23 
選項可以在列說明後提供。 即 sort -k3rn

注意,鍵可以被指定爲跨度。這裏-k3恰好是很好,因爲它是最後的跨度,但只使用第3列明確(在案件的進一步列添加),它應該被指定爲-k3,3, 同樣以三列按降序排序,然後列一個以升序(這可能是什麼是在這個例子中需要的話):

declare -A authors 
authors=([Pushkin]=10050 [Gogol]=23 [Dostoyevsky]=9999 [Tolstoy]=23) 
for k in "${!authors[@]}" 
do 
    echo $k ' - ' ${authors["$k"]} 
done | sort -k3,3rn -k1,1 

將輸出

 
Pushkin - 10050 
Dostoyevsky - 9999 
Gogol - 23 
Tolstoy - 23