2011-11-21 20 views
16

alıyorum şu çıktı:Bash ilişkisel dizi

:

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

Tek istediğim böyle çıktı elde etmektir: Aşağıdaki komut sonucudur

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999 

Pushkin - 100500 
Dostoyevsky - 9999 
Gogol - 23 

Bu, ilişkisel dizideki anahtarların değere göre sıralanması gerektiği anlamına gelir. Bunu yapmak için kolay bir yöntem var mı?

cevap

17

Kolayca 3 alanın sayısal sırasına göre, senin çıkışını sıralayabilirsiniz:

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

(1) sort komutu hakkında daha fazla bilgi için sıralama bakınız. Bu sadece çıktı çizgilerini sıralar; Bir diziyi doğrudan bash olarak sıralamak için hiçbir yol bilmiyorum.

Ayrıca, yukarıdakilerin size nasıl isim verebileceğini de göremiyorum ("Pushkin" ve ark.)). Bash, dizi anahtarları her zaman tamsayılardır.

+6

Bash 4,0 tuşları dizeleri olabilir ilişkilendirilebilir diziler ekler. –

+2

Eh, ben ... sen haklısın. Sadece declare -A yazarların ihtiyacı var. –

+1

Çözümünüz çalışıyor. Anlayabildiğim kadarıyla, sadece çıkış dizelerini, ilişkisel dizinin içeriğini değil, her neyse, üretilen çıktı, ihtiyacım olan şeydir. – Graf

7

Alternatif dizinleri sıralamak ve diziye döngü indeksler sıralanmış listesini kullanabilirsiniz:

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, tıslama: 'echo -e'. Printf '% s \ n' "$ {authors_indexes [@]}" 'dizisini, POSIX ihlallerine (yalnızca uzantılara değil, gerçek ihlallere) bağlı olmayan bir şekilde birden çok satıra genişletmek için düşünün: Herhangi bir argüman ters eğik çizgi içermedikçe veya '-n' mevcut değilse, bu durumda davranış tamamen uygulama tanımlıysa, metni yazdırmak için -n 'dışında bir şey gerekir. Veya 'printf'% s \ 0 '"$ {array [@]}" 'diziyi NULT-sınır dizeleri olarak genişletmek için, böylece anahtarlarınızda (örneğin * yasal olan) harf satırında yeni satırlar varsa bile çalışır). –

+0

... http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html, özellikle BAŞVURU KULLANIMI bölümüne bakınız. –

2

küresel sıralama seçeneği olarak rn kullanarak, @AndrewSchulman cevabını genişletme tüm sütunları tersine çevirir. Bu örnekte, aynı ilişkilendirici dizi değerine sahip yazarlar, adın tersi sırasına göre çıkarılacaktır. Örneğin belirli sütunları sıralamak için

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 

çıktısı

 
Pushkin - 10050 
Dostoyevsky - 9999 
Tolstoy - 23 
Gogol - 23 
Seçenek için

kolon belirtici sonra temin edilebilir. , yani sort -k3rn

Anahtarların açıklık olarak belirtilebileceğini unutmayın. -k3, son açıklık olduğu için iyi olur, ancak yalnızca 3. sütunu açıkça kullanmak için (daha fazla sütun eklendiyse), -k3,3, olarak belirtilmelidir. Benzer şekilde, sütun 3'e göre azalan sırada sıralanır ve sonra sütun (muhtemelen bu ne örnekte arzu edilir) artan sırada bir:

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 

irade çıkışı

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