Решение - не такое элегантное, как те, которые изменяют переменные * 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 , с логикой для добавления двоеточия к нп, если в нп уже есть текст . Блок 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