Wenn Sie Bash Version 4 oder höher ausführen (was in jeder modernen Linux-Version der Fall sein sollte), können Sie eindeutige Array-Werte in bash erhalten, indem Sie ein neues assoziatives Array erstellen, das jeden der Werte des ursprünglichen Arrays enthält. Etwas wie das:
$ 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
Dies funktioniert, weil in jedem Array (assoziativ oder traditionell, in jeder Sprache) jeder Schlüssel nur einmal angezeigt werden kann. Wenn die for
Schleife den zweiten Wert von aa
in erreicht a[2]
, überschreibt sie b[aa]
den ursprünglich für a[0]
.
Das Ausführen von Dingen in nativem Bash kann schneller sein als das Verwenden von Pipes und externen Tools wie z. B. sort
und uniq
bei größeren Datensätzen werden Sie wahrscheinlich eine bessere Leistung erzielen, wenn Sie eine leistungsfähigere Sprache wie awk, python usw. verwenden.
Wenn Sie sich sicher fühlen, können Sie die for
Schleife vermeiden , indem Sie die printf
Möglichkeit nutzen, das Format für mehrere Argumente zu recyceln, obwohl dies anscheinend erforderlich ist eval
. (Hör jetzt auf zu lesen, wenn du damit einverstanden bist.)
$ eval b=( $(printf ' ["%s"]=1' "${a[@]}") )
$ declare -p b
declare -A b=(["ac ad"]="1" [ac]="1" [aa]="1" [ad]="1" )
Der Grund, den diese Lösung erfordert, eval
besteht darin, dass Array-Werte vor der Wortteilung ermittelt werden. Dies bedeutet, dass die Ausgabe der Befehlssubstitution als einzelnes Wort und nicht als Satz von Schlüssel-Wert-Paaren betrachtet wird.
Während dies eine Subshell verwendet, werden nur Bash-Buildins verwendet, um die Array-Werte zu verarbeiten. Stellen Sie sicher, dass Sie Ihre Verwendung eval
mit kritischem Auge bewerten . Wenn Sie nicht zu 100% sicher sind, dass chepner, glenn jackman oder greycat keinen Fehler an Ihrem Code finden, verwenden Sie stattdessen die for-Schleife.
uniq=($(printf "%s\n" "${ids[@]}" | sort -u)); echo "${uniq[@]}"