PATH 환경 변수에서 디렉터리의 중복 복사본을 제거할 수 있는 bash 셸 함수를 작성하려고 합니다.
이 명령을 사용하여 한 줄 명령으로 이 작업을 수행할 수 있다는 말을 들었지만 awk
어떻게 해야 할지 모르겠습니다. 이 작업을 수행하는 방법을 아는 사람이 있나요?
답변1
아직 중복 항목이 없고 PATH
아직 존재하지 않는 디렉터리를 추가하려는 경우 셸만 사용하면 쉽게 이 작업을 수행할 수 있습니다.
for x in /path/to/add …; do
case ":$PATH:" in
*":$x:"*) :;; # already there
*) PATH="$x:$PATH";;
esac
done
다음은 중복 항목이 제거되는 쉘 조각입니다 $PATH
. 항목을 하나씩 살펴보고 아직 보지 못한 항목을 복사합니다.
if [ -n "$PATH" ]; then
old_PATH=$PATH:; PATH=
while [ -n "$old_PATH" ]; do
x=${old_PATH%%:*} # the first remaining entry
case $PATH: in
*:"$x":*) ;; # already there
*) PATH=$PATH:$x;; # not there yet
esac
old_PATH=${old_PATH#*:}
done
PATH=${PATH#:}
unset old_PATH x
fi
답변2
이것은이해할 수 있는한 줄 솔루션은 모든 올바른 작업을 수행합니다. 즉, 중복을 제거하고 경로 순서를 유지하며 끝에 콜론을 추가하지 않습니다. 따라서 원래 경로와 똑같이 동작하는 중복 제거된 PATH를 제공해야 합니다.
PATH="$(perl -e 'print join(":", grep { not $seen{$_}++ } split(/:/, $ENV{PATH}))')"
split(/:/, $ENV{PATH})
콜론( )으로 분할하고 use를 사용하여 첫 grep { not $seen{$_}++ }
번째 발생을 제외한 모든 중복 경로 인스턴스를 필터링한 다음 콜론( print join(":", ...)
)으로 구분된 나머지 경로를 다시 결합하고 결과를 인쇄합니다.
더 많은 구조와 다른 변수의 중복을 제거하는 기능을 원한다면 다음 코드 조각을 사용해 보세요. 현재 내 구성에서 사용하고 있습니다.
# Deduplicate path variables
get_var () {
eval 'printf "%s\n" "${'"$1"'}"'
}
set_var () {
eval "$1=\"\$2\""
}
dedup_pathvar () {
pathvar_name="$1"
pathvar_value="$(get_var "$pathvar_name")"
deduped_path="$(perl -e 'print join(":",grep { not $seen{$_}++ } split(/:/, $ARGV[0]))' "$pathvar_value")"
set_var "$pathvar_name" "$deduped_path"
}
dedup_pathvar PATH
dedup_pathvar MANPATH
이 코드는 PATH 및 MANPATH의 중복을 제거하며 dedup_pathvar
콜론으로 구분된 경로 목록을 보유하는 다른 변수(예: PYTHONPATH)를 쉽게 호출할 수 있습니다.
답변3
세련된 것은 다음과 같습니다.
printf %s "$PATH" | awk -v RS=: -v ORS=: '!arr[$0]++'
더 길어짐(작동 방식 참조):
printf %s "$PATH" | awk -v RS=: -v ORS=: '{ if (!arr[$0]++) { print $0 } }'
좋아, 당신은 Linux를 처음 사용하기 때문에 뒤에 오는 ":" 없이 PATH를 실제로 설정하는 방법은 다음과 같습니다.
PATH=`printf %s "$PATH" | awk -v RS=: '{ if (!arr[$0]++) {printf("%s%s",!ln++?"":":",$0)}}'`
그런데, PATH에 ":"가 포함된 디렉터리가 없는지 확인하세요. 그렇지 않으면 혼란스러워질 것입니다.
일부 크레딧:
답변4
awk가 아닌 oneliner를 추가하는 한:
PATH=$(zsh -fc "typeset -TU P=$PATH p; echo \$P")
(간단할 수도 있지만 zsh는 항상 수정할 수 있는 PATH=$(zsh -fc 'typeset -U path; echo $PATH')
최소한 하나의 구성 파일을 읽습니다 .)zshenv
PATH
두 가지 훌륭한 zsh 기능을 사용합니다.
- 배열과 관련된 스칼라(
typeset -T
) - 및 중복된 값을 자동으로 제거하는 배열(
typeset -U
).