Si está ejecutando Bash versión 4 o superior (que debería ser el caso en cualquier versión moderna de Linux), puede obtener valores de matriz únicos en bash creando una nueva matriz asociativa que contenga cada uno de los valores de la matriz original. Algo como esto:
$ 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
Esto funciona porque en cualquier matriz (asociativa o tradicional, en cualquier idioma), cada clave solo puede aparecer una vez. Cuando el for
bucle llega al segundo valor de aa
in a[2]
, sobrescribe el b[aa]
que se estableció originalmente a[0]
.
Hacer cosas en bash nativo puede ser más rápido que usar tuberías y herramientas externas como sort
y uniq
, aunque para conjuntos de datos más grandes, probablemente verá un mejor rendimiento si usa un lenguaje más poderoso como awk, python, etc.
Si se siente seguro, puede evitar el for
bucle usando printf
la capacidad de reciclar su formato para múltiples argumentos, aunque esto parece ser necesario eval
. (Deja de leer ahora si estás de acuerdo con eso).
$ eval b=( $(printf ' ["%s"]=1' "${a[@]}") )
$ declare -p b
declare -A b=(["ac ad"]="1" [ac]="1" [aa]="1" [ad]="1" )
La razón por la que esta solución requiere eval
es que los valores de la matriz se determinen antes de la división de palabras. Eso significa que la salida de la sustitución del comando se considera una sola palabra lugar de un conjunto de pares clave = valor.
Si bien esto usa una subcapa, solo usa elementos internos de bash para procesar los valores de la matriz. Asegúrese de evaluar su uso eval
con ojo crítico. Si no está 100% seguro de que chepner, glenn jackman o greycat no encontrarán fallas en su código, use el bucle for en su lugar.
uniq=($(printf "%s\n" "${ids[@]}" | sort -u)); echo "${uniq[@]}"