Se você estiver executando o Bash versão 4 ou superior (o que deve ser o caso em qualquer versão moderna do Linux), poderá obter valores de array exclusivos em bash criando um novo array associativo que contém cada um dos valores do array original. Algo assim:
$ 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
Isso funciona porque em qualquer array (associativo ou tradicional, em qualquer idioma), cada chave só pode aparecer uma vez. Quando o for
loop chega ao segundo valor de aa
in a[2]
, ele substitui o b[aa]
que foi definido originalmente para a[0]
.
Fazer coisas no bash nativo pode ser mais rápido do que usar canais e ferramentas externas como sort
e uniq
, embora para conjuntos de dados maiores você provavelmente verá um desempenho melhor se usar uma linguagem mais poderosa como awk, python, etc.
Se você estiver se sentindo confiante, pode evitar o for
loop usando printf
a capacidade de reciclar seu formato para vários argumentos, embora isso pareça exigir eval
. (Pare de ler agora se você estiver bem com isso.)
$ eval b=( $(printf ' ["%s"]=1' "${a[@]}") )
$ declare -p b
declare -A b=(["ac ad"]="1" [ac]="1" [aa]="1" [ad]="1" )
O motivo pelo qual essa solução exige eval
é que os valores da matriz sejam determinados antes da divisão das palavras. Isso significa que a saída da substituição do comando é considerada uma única palavra em vez de um conjunto de pares chave = valor.
Embora use um subshell, ele usa apenas bash builtins para processar os valores do array. Certifique-se de avaliar o uso do eval
com um olhar crítico. Se você não estiver 100% confiante de que chepner ou glenn jackman ou greycat não encontrariam nenhuma falha em seu código, use o loop for.
uniq=($(printf "%s\n" "${ids[@]}" | sort -u)); echo "${uniq[@]}"