Рішення - не таке витончене, як те, яке змінює * змінні RS, але, можливо, досить зрозуміле:
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`
Вся програма працює в блоках BEGIN і END . Він витягує вашу змінну PATH з навколишнього середовища, розділяючи її на одиниці. Потім він повторюється над масивом p (який створюється в порядку split()
). Масив e - асоціативний масив, який використовується для визначення того, чи раніше ми бачили чи ні поточний елемент шляху (наприклад, / usr / local / bin ), а якщо ні, додається до np , з логікою додавання двокрапки до np, якщо в np вже є текст . Блок END просто перегукується np . Це можна додатково спростити, додавши-F:
прапор, виключаючи третій аргумент split()
(як він по замовчуванням FS ), і зміна np = np ":"
в np = np FS
, даючи нам:
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
Наївно, я вважав, що for(element in array)
це збереже порядок, але це не так, тому моє оригінальне рішення не працює, оскільки люди будуть засмучуватися, якщо хтось раптом порушив їх порядок $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