Một giải pháp - không phải là một giải pháp thanh lịch như những giải pháp thay đổi các biến * RS, nhưng có lẽ rõ ràng hợp lý:
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`
Toàn bộ chương trình hoạt động trong các khối BEGIN và END . Nó kéo biến PATH của bạn khỏi môi trường, chia nó thành các đơn vị. Sau đó, nó lặp lại trên mảng kết quả p (được tạo theo thứ tự bởi split()
). Mảng e là một mảng kết hợp được sử dụng để xác định xem chúng ta đã thấy phần tử đường dẫn hiện tại (ví dụ / usr / local / bin ) hay chưa, và nếu không, sẽ được thêm vào np , với logic để nối thêm dấu hai chấm vào np nếu đã có văn bản trong np . Khối END chỉ đơn giản là echos np . Điều này có thể được đơn giản hóa hơn nữa bằng cách thêm-F:
gắn cờ, loại bỏ đối số thứ ba thành split()
(vì nó mặc định là FS ) và thay đổi np = np ":"
thành np = np FS
, cho chúng ta:
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
Ngây thơ, tôi tin rằng for(element in array)
sẽ giữ trật tự, nhưng không, vì vậy giải pháp ban đầu của tôi không hiệu quả, vì mọi người sẽ khó chịu nếu ai đó đột nhiên xáo trộn trật tự của họ $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