2011-11-21 13 views
16

uzyskać następujący wynik:Bash asocjacyjna sortowania

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999 

co jest wynikiem następującego scenariusza:

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

Wszystko czego chcę to dostać wyjście takiego:

Pushkin - 100500 
Dostoyevsky - 9999 
Gogol - 23 

co oznacza, że ​​klucze w tablicy asocjacyjnej powinny być posortowane według wartości. Czy istnieje łatwa metoda?

Odpowiedz

17

można łatwo sortować wyjście, w malejącej kolejności numerycznej pola 3:

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

Zobacz sort (1) dla więcej o poleceniu sort. To po prostu sortuje linie wyjściowe; Nie znam sposobu sortowania tablicy bezpośrednio w bashu.

Nie widzę również, jak powyższe mogą dawać Ci nazwy ("Puszkin" i in.) Jako klucze tablicy. W bashu klucze tablicy są zawsze liczbami całkowitymi.

+6

Bash 4.0 dodaje tablic asocjacyjnych, gdzie klucze mogą być ciągi. –

+2

Cóż, będę ... masz rację. Po prostu potrzebuje 'declare -A autorzy'. –

+1

Twoje rozwiązanie działa. O ile rozumiem, po prostu sortuje ciągi wyjściowe, a nie zawartość tablicy asocjacyjnej, ale w każdym razie, produkowany wynik jest tym, czego potrzebuję. – Graf

7

Alternatywnie można sortować indeksów i użyć posortowana lista indeksów pętli tablicy:

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, syk re: 'echo -e'. Rozważ 'printf '% s \ n'" $ {authors_indexes [@]} "' aby rozwinąć tablicę na wiele linii w sposób niezależny od naruszenia POSIX sh (nie tylko rozszerzenia, ale rzeczywiste naruszenia: dowolny argument inne niż '-n' jest wymagane, aby wydrukować jego tekst, chyba że zawiera on ukośnik odwrotny lub' -n' jest obecny, w którym to przypadku zachowanie jest w pełni zdefiniowane przez implementację). Lub 'printf '% s \ 0'" $ {tablica [@]} "', aby rozwinąć tablicę jako łańcuchy NUL-delimit, a więc w sposób, który działa nawet jeśli masz dosłowne znaki nowej linii w swoich kluczach (które * są * legalne). –

+0

... patrz http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html, w szczególności sekcja ZASTOSOWANIE APLIKACJI. –

2

Rozszerzanie odpowiedź od @AndrewSchulman korzystając -rn jako opcja sortowania globalnej odwraca wszystkie kolumny. W tym przykładzie autorzy o tej samej wartości tablicy asocjacyjnej będą wyprowadzani przez odwrotną kolejność nazw.

Na przykład

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 

wyjście będzie

 
Pushkin - 10050 
Dostoyevsky - 9999 
Tolstoy - 23 
Gogol - 23 
metodami sortowania konkretne kolumny mogą być dostarczone po specyfikatorem kolumny. tj. sort -k3rn

Należy pamiętać, że klucze można określić jako przęsła. W tym przypadku wartość parametru -k3 jest w porządku, ponieważ jest to ostatni zakres, ale w celu jawnego użycia tylko kolumny 3 (w przypadku dodania kolejnych kolumn), należy ją określić jako -k3,3, Podobnie do sortowania według kolumny trzeciej w porządku malejącym, a następnie w kolumnie jeden w porządku rosnącym (co jest chyba to, co jest pożądane w tym przykładzie):

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 

wyjście wola

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

Powiązane problemy