Jeśli używasz Bash w wersji 4 lub nowszej (co powinno mieć miejsce w każdej nowoczesnej wersji Linuksa), możesz uzyskać unikalne wartości tablic w bash, tworząc nową tablicę asocjacyjną zawierającą każdą z wartości oryginalnej tablicy. Coś takiego:
$ a=(aa ac aa ad "ac ad")
$ declare -A b
$ for i in "${a[@]}"; do b["$i"]=1; done
$ printf '%s\n' "${!b[@]}"
ac ad
ac
aa
ad
To działa, ponieważ w dowolnej tablicy (asocjacyjnej lub tradycyjnej, w dowolnym języku) każdy klucz może wystąpić tylko raz. Kiedy for
pętla osiąga drugą wartość aa
in a[2]
, nadpisuje b[aa]
pierwotnie ustawioną wartość a[0]
.
Robienie rzeczy w natywnym bashu może być szybsze niż używanie potoków i zewnętrznych narzędzi, takich jak sort
i uniq
, chociaż w przypadku większych zestawów danych prawdopodobnie zobaczysz lepszą wydajność, jeśli użyjesz mocniejszego języka, takiego jak awk, python itp.
Jeśli czujesz się pewnie, możesz uniknąć for
pętli, korzystając printf
z możliwości ponownego wykorzystania formatu dla wielu argumentów, chociaż wydaje się to wymagać eval
. (Przestań czytać teraz, jeśli nie masz nic przeciwko.)
$ eval b=( $(printf ' ["%s"]=1' "${a[@]}") )
$ declare -p b
declare -A b=(["ac ad"]="1" [ac]="1" [aa]="1" [ad]="1" )
Powodem, dla którego to rozwiązanie wymaga, eval
jest to, że wartości tablic są określane przed podziałem na słowa. Oznacza to, że wynik podstawienia polecenia jest traktowany jako pojedyncze słowo a nie zestaw par klucz = wartość.
Chociaż używa podpowłoki, używa tylko wbudowanych bash do przetwarzania wartości tablic. Pamiętaj, aby eval
krytycznym okiem ocenić swoje użycie . Jeśli nie masz 100% pewności, że chepner, glenn jackman lub greycat nie znajdzie żadnych błędów w twoim kodzie, użyj zamiast tego pętli for.
uniq=($(printf "%s\n" "${ids[@]}" | sort -u)); echo "${uniq[@]}"