내 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})
)으로 분할하고 사용을 사용하여 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")
(간단할 수도 있지만 PATH=$(zsh -fc 'typeset -U path; echo $PATH')
zsh는 항상 수정할 수 있는 하나 이상의 zshenv
구성 파일을 읽습니다 PATH
.)
두 가지 멋진 zsh 기능을 사용합니다.
- 배열에 연결된 스칼라(
typeset -T
) - 및 중복된 값을 자동으로 제거하는 배열(
typeset -U
).