Uma solução - não tão elegante quanto as que alteram as variáveis * RS, mas talvez razoavelmente claras:
PATH='awk 'BEGIN {np="";split(ENVIRON["PATH"],p,":"); for(x=0;x<length(p);x++) { pe=p[x]; if(e[pe] != "") continue; e[pe] = pe; if(np != "") np=np ":"; np=np pe}} END { print np }' /dev/null'
O programa inteiro funciona nos blocos BEGIN e END . Ele puxa sua variável PATH do ambiente, dividindo-a em unidades. Em seguida, itera sobre o array resultante p (que é criado na ordem de split()
). A matriz e é uma matriz associativa usada para determinar se já vimos ou não o elemento do caminho atual (por exemplo, / usr / local / bin ) e se não, é anexado a np , com lógica para acrescentar dois pontos a np se já houver texto em np . O bloco END simplesmente ecoa np . Isso poderia ser ainda mais simplificado adicionando o sinal -F:
, eliminando o terceiro argumento para split()
(como padrão FS ), e alterando np = np ":"
para np = np FS
, nos dando:
awk -F: 'BEGIN {np="";split(ENVIRON["PATH"],p); for(x=0;x<length(p);x++) { pe=p[x]; if(e[pe] != "") continue; e[pe] = pe; if(np != "") np=np FS; np=np pe}} END { print np }' /dev/null
Naïvely, eu acreditei que for(element in array)
preservaria a ordem, mas não, então minha solução original não funciona, pois as pessoas ficariam chateadas se alguém subitamente alterasse a ordem de seus $PATH
:
awk 'BEGIN {np="";split(ENVIRON["PATH"],p,":"); for(x in p) { pe=p[x]; if(e[pe] != "") continue; e[pe] = pe; if(np != "") np=np ":"; np=np pe}} END { print np }' /dev/null