Une solution - pas aussi élégante que celles qui modifient les variables * RS, mais peut-être raisonnablement claire:
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`
L'ensemble du programme fonctionne dans les blocs BEGIN et END . Il extrait votre variable PATH de l’environnement et le divise en unités. Il itère ensuite sur le tableau résultant p (qui est créé dans l'ordre split()
). Le tableau e est un tableau associatif utilisé pour déterminer si nous avons déjà vu ou non l'élément de chemin actuel (par exemple, / usr / local / bin ), et si ce n'est pas le cas, est ajouté à np , avec la logique pour ajouter un point-virgule à np s'il y a déjà du texte dans np . Le bloc END renvoie simplement np . Cela pourrait être encore simplifié en ajoutant le-F:
flag, en éliminant le troisième argument de split()
(comme il est par défaut FS ), et en passant np = np ":"
à np = np FS
, nous donnant:
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ïvement, je pensais que for(element in array)
cela préserverait l'ordre, mais ce n'est pas le cas, donc ma solution initiale ne fonctionne pas, car les gens s'énerveraient si quelqu'un changeait soudainement l'ordre de leur $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