Eine Lösung - nicht so elegant wie jene, die die * RS-Variablen ändern, aber vielleicht einigermaßen klar:
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`
Das gesamte Programm arbeitet in den Bausteinen BEGIN und END . Es zieht Ihre PATH-Variable aus der Umgebung und teilt sie in Einheiten auf. Es durchläuft dann das resultierende Array p (das in der Reihenfolge von erstellt wird split()
). Das Array e ist ein assoziatives Array, mit dem bestimmt wird, ob wir das aktuelle Pfadelement (z. B. / usr / local / bin ) bereits gesehen haben oder nicht. Wenn nicht, wird es an np angehängt , wobei ein Doppelpunkt angefügt wird np wenn es bereits text in np gibt . Der END- Block gibt einfach np wieder . Dies könnte noch weiter vereinfacht werden, indem die-F:
flag, eliminiert das dritte Argument von split()
(da es standardmäßig FS ist ) und ändert sich np = np ":"
zu np = np FS
, was uns ergibt:
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
Naiv, ich habe geglaubt, das for(element in array)
würde Ordnung bewahren, aber das tut es nicht, also funktioniert meine ursprüngliche Lösung nicht, da sich die Leute aufregen würden, wenn jemand plötzlich die Reihenfolge ihrer Dinge durcheinanderwirbelt $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