Bash에서 $PATH 변수에서 경로를 제거하는 가장 우아한 방법은 무엇입니까?
또는 일반적으로 Bash 환경 변수의 콜론으로 구분된 목록에서 항목을 제거하려면 어떻게 해야 합니까?
저는 몇 년 전에 더 발전된 형태의 Bash 변수 확장을 사용하는 간단한 방법을 본 적이 있다고 생각했지만, 만약 그렇다면 저는 그것에 대해 전혀 알지 못합니다.구글의 빠른 검색은 놀랍게도 관련된 결과가 거의 없었고 "단순" 또는 "우아"라고 부를 만한 결과도 없었습니다.예를 들어 sed와 awk를 각각 사용하는 두 가지 방법은 다음과 같습니다.
PATH=$(echo $PATH | sed -e 's;:\?/home/user/bin;;' -e 's;/home/user/bin:\?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)
직접적인 것은 존재하지 않습니까?Bash에 split() 함수와 유사한 것이 있습니까?
의도적으로 모호한 질문에 대해 사과해야 할 것 같습니다. 저는 좋은 토론을 유발하기보다는 특정 사용 사례를 해결하는 데 관심이 없었습니다.다행히도, 제가 잡았어요!
여기에는 매우 영리한 기술들이 있습니다.결국, 저는 제 툴박스에 다음 세 가지 기능을 추가했습니다.하는데, 는 주로 에 기반을 두고 있습니다.awk의 RS 변수입니다.
path_append () { path_remove $1; export PATH="$PATH:$1"; }
path_prepend () { path_remove $1; export PATH="$1:$PATH"; }
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; }
거기서 유일한 진정한 결함은 사용하는 것입니다.sed후행 결장을 제거합니다.하지만 마틴의 나머지 해결책이 얼마나 간단한지를 고려할 때, 저는 기꺼이 그것을 감수할 것입니다!
관련 질문:셸 스크립트에서 $PATH 요소를 조작하려면 어떻게 해야 합니까?
내 더러운 해킹:
echo ${PATH} > t1
vi t1
export PATH=$(cat t1)
어색한 1분:
# Strip all paths with SDE in them.
#
export PATH=`echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}'`
편집: 아래 설명에 응답합니다.
$ export a="/a/b/c/d/e:/a/b/c/d/g/k/i:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i"
$ echo ${a}
/a/b/c/d/e:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i
## Remove multiple (any directory with a: all of them)
$ echo ${a} | awk -v RS=: -v ORS=: '/a/ {next} {print}'
## Works fine all removed
## Remove multiple including last two: (any directory with g)
$ echo ${a} | awk -v RS=: -v ORS=: '/g/ {next} {print}'
/a/b/c/d/e:/a/b/c/d/f:
## Works fine: Again!
보안 문제에 대응하여 편집: (질문과 관련이 없음)
export PATH=$(echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}' | sed 's/:*$//')
항목을 하여 남아 콜론이 으로 추가됩니다..당신의 길로.
대체와 관련된 큰 문제는 최종 사례이므로, 최종 사례를 다른 사례와 다르지 않게 만드는 것은 어떻습니까?경로의 시작과 끝에 이미 콜론이 있는 경우 콜론으로 묶인 원하는 문자열을 검색할 수 있습니다.현재 상태로는, 우리는 쉽게 그 콜론들을 추가하고 나중에 그것들을 제거할 수 있습니다.
# PATH => /bin:/opt/a dir/bin:/sbin
WORK=:$PATH:
# WORK => :/bin:/opt/a dir/bin:/sbin:
REMOVE='/opt/a dir/bin'
WORK=${WORK/:$REMOVE:/:}
# WORK => :/bin:/sbin:
WORK=${WORK%:}
WORK=${WORK#:}
PATH=$WORK
# PATH => /bin:/sbin
순수 bash :).
제가 생각할 수 있는 가장 간단한 해결책은 다음과 같습니다.
#!/bin/bash
IFS=:
# convert it to an array
t=($PATH)
unset IFS
# perform any array operations to remove elements from the array
t=(${t[@]%%*usr*})
IFS=:
# output the new array
echo "${t[*]}"
위의 예에서는 "usr"을 포함하는 $PATH의 모든 요소를 제거합니다."*usr*"을 "/home/user/bin"으로 대체하여 해당 요소만 제거할 수 있습니다.
업데이트 퍼슈버(퍼슈버)
는 내생공간들은에기각a의 이 있다고 하지만,$PATH끔찍한 아이디어입니다. 여기 이를 처리하는 솔루션이 있습니다.
PATH=$(IFS=':';t=($PATH);n=${#t[*]};a=();for ((i=0;i<n;i++)); do p="${t[i]%%*usr*}"; [ "${p}" ] && a[i]="${p}"; done;echo "${a[*]}");
또는
IFS=':'
t=($PATH)
n=${#t[*]}
a=()
for ((i=0;i<n;i++)); do
p="${t[i]%%*usr*}"
[ "${p}" ] && a[i]="${p}"
done
echo "${a[*]}"
다음은 현재 허용되고 가장 높은 평가를 받은 답변에도 불구하고 PATH에 보이지 않는 문자를 추가하지 않고 공백이 포함된 경로를 처리할 수 있는 하나의 라이너입니다.
export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/cygwin/" | tr "\n" ":"); echo ${p%:})
개인적으로, 저는 이것이 읽기/이해하기 쉽다고 생각하며, 그것은 awk를 사용하는 대신 일반적인 명령만 포함합니다.
다음은 다음과 같은 솔루션입니다.
- 순수한 바쉬,
- 다른 프로세스(예: 'sed' 또는 'sess')를 호출하지 않습니다.
- 하지 않음
IFS, - 하위 셸을 포크하지 않습니다.
- 공백이 있는 경로를 처리합니다.
인수제다니에 있는 합니다.
PATH.경로() {에서 제거로컬 pdp=":$1:"d=":$PATH:"d=${d//$p/:}d=${d/#:/}PATH=${d/%:/}}
저는 1991년부터 있었던 bash 배포판의 함수를 사용하고 있습니다., 페도라의 bash-docs에서 되었습니다./etc/profile하지만 더 이상은...
$ rpm -ql bash-doc |grep pathfunc
/usr/share/doc/bash-4.2.20/examples/functions/pathfuncs
$ cat $(!!)
cat $(rpm -ql bash-doc |grep pathfunc)
#From: "Simon J. Gerraty" <sjg@zen.void.oz.au>
#Message-Id: <199510091130.VAA01188@zen.void.oz.au>
#Subject: Re: a shell idea?
#Date: Mon, 09 Oct 1995 21:30:20 +1000
# NAME:
# add_path.sh - add dir to path
#
# DESCRIPTION:
# These functions originated in /etc/profile and ksh.kshrc, but
# are more useful in a separate file.
#
# SEE ALSO:
# /etc/profile
#
# AUTHOR:
# Simon J. Gerraty <sjg@zen.void.oz.au>
# @(#)Copyright (c) 1991 Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
# Permission to copy, redistribute or otherwise
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
# is $1 missing from $2 (or PATH) ?
no_path() {
eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
}
function __path_remove(){
local D=":${PATH}:";
[ "${D/:$1:/:}" != "$D" ] && PATH="${D/:$1:/:}";
PATH="${PATH/#:/}";
export PATH="${PATH/%:/}";
}
내 .bashrc 파일에서 찾아냈어요.PATH를 가지고 놀다가 잃어버리면, awk/sed/grep를 사용할 수 없게 됩니다 :-)
지금까지 찾은 가장 좋은 순수 bash 옵션은 다음과 같습니다.
function path_remove {
# Delete path by parts so we can never accidentally remove sub paths
PATH=${PATH//":$1:"/":"} # delete any instances in the middle
PATH=${PATH/#"$1:"/} # delete any instance at the beginning
PATH=${PATH/%":$1"/} # delete any instance at the end
}
이는 Superuser에 아직 디렉터리가 없는 경우 $PATH에 디렉터리를 추가하여 코멘트에 언급된 문제를 수정한다는 답변이 정확하지 않은 것에 기반으로 합니다.
설명을 원하지 않는다면 분명히 이것은 한 줄 기능으로 만들 수 있습니다.
Scratch는 Linux From Scratch에서 세 합니다./etc/profile:
# Functions to help us manage paths. Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
local IFS=':'
local NEWPATH
local DIR
local PATHVARIABLE=${2:-PATH}
for DIR in ${!PATHVARIABLE} ; do
if [ "$DIR" != "$1" ] ; then
NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
fi
done
export $PATHVARIABLE="$NEWPATH"
}
pathprepend () {
pathremove $1 $2
local PATHVARIABLE=${2:-PATH}
export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}
pathappend () {
pathremove $1 $2
local PATHVARIABLE=${2:-PATH}
export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}
export -f pathremove pathprepend pathappend
참조: http://www.linuxfromscratch.org/blfs/view/svn/postlfs/profile.html
음, bash에서는 정규 표현을 지원하기 때문에 간단하게 할 수 있습니다.
PATH=${PATH/:\/home\/user\/bin/}
저는 여기에 (아크도 사용하여) 답변을 썼습니다.하지만 그게 당신이 찾고 있는 것인지는 잘 모르겠습니다.적어도 한 줄에 맞추려고 노력하는 대신에, 그것이 무엇을 하는지는 제가 보기에 분명해 보입니다.하지만 물건만 제거하는 간단한 라이너는 추천합니다.
echo $PATH | tr ':' '\n' | awk '$0 != "/bin"' | paste -sd:
교체는
echo $PATH | tr ':' '\n' |
awk '$0 != "/bin"; $0 == "/bin" { print "/bar" }' | paste -sd:
또는 (가독성이 떨어지지만)
echo $PATH | tr ':' '\n' | awk '$0 == "/bin" { print "/bar"; next } 1' | paste -sd:
어쨌든, 같은 질문과 많은 유용한 답변은 여기를 참조하십시오.
@BenBlank의 원래 질문에 대한 업데이트에 나와 있는 세 가지 기능이 마음에 듭니다.일반화하기 위해 PATH 또는 원하는 다른 환경 변수를 설정할 수 있는 2-인수 형식을 사용합니다.
path_append () { path_remove $1 $2; export $1="${!1}:$2"; }
path_prepend () { path_remove $1 $2; export $1="$2:${!1}"; }
path_remove () { export $1="`echo -n ${!1} | awk -v RS=: -v ORS=: '$1 != "'$2'"' | sed 's/:$//'`"; }
사용 예:
path_prepend PATH /usr/local/bin
path_append PERL5LIB "$DEVELOPMENT_HOME/p5/src/perlmods"
공백이 포함된 경로 이름을 적절하게 처리할 수 있도록 따옴표도 추가했습니다.
Bash에서 $PATH 변수에서 경로를 제거하는 가장 우아한 방법은 무엇입니까?
어색한 것보다 더 우아한 것은 무엇입니까?
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`;
Python! 더 읽기 쉽고 유지 관리가 가능한 솔루션이며, 실제로 원하는 작업을 수행하고 있는지 쉽게 확인할 수 있습니다.
첫 번째 경로 요소를 제거하시겠습니까?
PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
((으)로부터의 echo,os.getenv['PATH']조금 더 짧고 위와 같은 결과를 제공할 수도 있지만, Python이 그 환경 변수로 뭔가를 할 수도 있어서 걱정이 되기 때문에 당신이 관심 있는 환경에서 직접 파이프로 연결하는 것이 가장 좋을 것입니다.)
끝에서 제거하는 것과 유사합니다.
PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
예를 들어 .bashrc 파일에 저장할 수 있는 재사용 가능한 셸 기능을 만들려면 다음과 같이 하십시오.
strip_path_first () {
PATH="$(echo "$PATH" |
python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
}
strip_path_last () {
PATH="$(echo "$PATH" |
python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
}
예, 예를 들어 PATH의 끝에 콜론을 배치하면 경로를 제거하는 작업이 다소 서툴고 오류가 발생하기 쉽습니다.
path_remove () {
declare i newPATH
newPATH="${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
#echo ${@:${i}:1}
newPATH="${newPATH//${@:${i}:1}:/}"
done
export PATH="${newPATH%:}"
return 0;
}
path_remove_all () {
declare i newPATH
shopt -s extglob
newPATH="${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
newPATH="${newPATH//+(${@:${i}:1})*([^:]):/}"
#newPATH="${newPATH//+(${@:${i}:1})*([^:])+(:)/}"
done
shopt -u extglob
export PATH="${newPATH%:}"
return 0
}
path_remove /opt/local/bin /usr/local/bin
path_remove_all /opt/local /usr/local
$PATH에서 중복 항목을 제거하는 것이 걱정된다면, IMHO라는 가장 우아한 방법은 처음부터 중복 항목을 추가하지 않는 것입니다.한 줄로:
if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$folder" ) ; then PATH=$PATH:$folder ; fi
$folder는 임의로 대체할 수 있으며 공백("/home/user/my documents")을 포함할 수 있습니다.
지금까지 발견한 가장 우아한 순수한 바쉬 솔루션:
pathrm () {
local IFS=':'
local newpath
local dir
local pathvar=${2:-PATH}
for dir in ${!pathvar} ; do
if [ "$dir" != "$1" ] ; then
newpath=${newpath:+$newpath:}$dir
fi
done
export $pathvar="$newpath"
}
pathprepend () {
pathrm $1 $2
local pathvar=${2:-PATH}
export $pathvar="$1${!pathvar:+:${!pathvar}}"
}
pathappend () {
pathrm $1 $2
local pathvar=${2:-PATH}
export $pathvar="${!pathvar:+${!pathvar}:}$1"
}
의 다른 솔루션은 하고 제된다솔대의문은부일자의치열만존다에며하음같다과경과 같은 .,..또는~아래의 bash 함수는 인수와 경로 세그먼트의 디렉터리 문자열을 확인하여 논리 디렉터리 일치와 문자열 일치를 찾습니다.
rm_from_path() {
pattern="${1}"
dir=''
[ -d "${pattern}" ] && dir="$(cd ${pattern} && pwd)" # resolve to absolute path
new_path=''
IFS0=${IFS}
IFS=':'
for segment in ${PATH}; do
if [[ ${segment} == ${pattern} ]]; then # string match
continue
elif [[ -n ${dir} && -d ${segment} ]]; then
segment="$(cd ${segment} && pwd)" # resolve to absolute path
if [[ ${segment} == ${dir} ]]; then # logical directory match
continue
fi
fi
new_path="${new_path}${IFS}${segment}"
done
new_path="${new_path/#${IFS}/}" # remove leading colon, if any
IFS=${IFS0}
export PATH=${new_path}
}
테스트:
$ mkdir -p ~/foo/bar/baz ~/foo/bar/bif ~/foo/boo/bang
$ PATH0=${PATH}
$ PATH=~/foo/bar/baz/.././../boo/././../bar:${PATH} # add dir with special names
$ rm_from_path ~/foo/boo/../bar/. # remove same dir with different special names
$ [ ${PATH} == ${PATH0} ] && echo 'PASS' || echo 'FAIL'
이 질문은 모두가 선호해야 하는 BASH에 대한 질문이라는 것을 알고 있지만, 저는 대칭성을 즐기고 때때로 "csh"를 사용해야 하기 때문에 위의 "path_prepend()", "path_append()" 및 "path_remove()"와 동등한 우아한 솔루션을 구축했습니다.
요점은 "csh"에는 함수가 없기 때문에 함수와 같은 역할을 하는 작은 셸 스크립트를 개인 bin 디렉토리에 넣었습니다.지정된 환경 변수를 변경하기 위해 이러한 스크립트의 소스에 대한 별칭을 생성합니다.
~/bin/_path_remove.csh:
set _resolve = `eval echo $2`
setenv $1 `eval echo -n \$$1 | awk -v RS=: -v ORS=: '$1 != "'${_resolve}'"' | sed 's/:$//'`;
unset _resolve
~/bin/_path_message.csh:
source ~/bin/_path_remove.csh $1 $2
set _base = `eval echo \$$1`
set _resolve = `eval echo $2`
setenv $1 ${_base}:${_resolve}
unset _base _resolve
~/bin/_path_binend.csh:
source ~/bin/_path_remove.csh $1 $2
set _base = `eval echo \$$1`
set _resolve = `eval echo $2`
setenv $1 ${_resolve}:${_base}
unset _base _resolve
~/bin/.cshrc:
…
alias path_remove "source ~/bin/_path_remove.csh '\!:1' '\!:2'"
alias path_append "source ~/bin/_path_append.csh '\!:1' '\!:2'"
alias path_prepend "source ~/bin/_path_prepend.csh '\!:1' '\!:2'"
…
이런 식으로 사용할 수 있습니다.
%(csh)> path_append MODULEPATH ${HOME}/modulefiles
이것은 우아한 방법이 없기 때문에 문제를 피하기 위해 해결책을 재정렬하여 문제를 피하는 것이 좋습니다. 즉, 해결책을 무너뜨리려고 하기보다는 길을 닦는 것입니다.
당신의 진짜 문제 상황을 알면 좀 더 구체적으로 말할 수 있을 겁니다.그 사이에, 저는 소프트웨어 빌드를 컨텍스트로 사용할 것입니다.
소프트웨어 빌드의 일반적인 문제는 일부 시스템에서 소프트웨어 빌드가 손상된다는 것이며, 이는 궁극적으로 누군가 기본 셸(PATH 및 기타 환경 변수)을 구성한 방식으로 인해 발생합니다.셸 환경을 완전히 지정하여 빌드 스크립트에 영향을 주지 않도록 하는 것이 가장 좋은 해결책입니다.빌드 스크립트를 코딩하여 컴파일러, 라이브러리, 도구, 구성 요소 등 사용자가 제어하는 어셈블리 조각을 기반으로 PATH 및 기타 환경 변수를 설정합니다.구성 가능한 각 항목을 개별적으로 설정하고 확인한 다음 스크립트에서 적절하게 사용할 수 있는 항목으로 만듭니다.
예를 들어, 저는 새로운 고용주에게 물려받은 Maven 기반의 WebLogic 대상 Java 빌드를 가지고 있습니다.빌드 스크립트는 취약한 것으로 악명이 높았으며, 다른 신입 사원과 저는 3주(풀타임은 아니지만, 여기저기서뿐만 아니라 아직도 많은 시간)를 들여 이 스크립트를 기계에서 작동시켰습니다.중요한 단계는 어떤 Java, 어떤 Maven, 어떤 WebLogic이 호출되는지 정확히 알 수 있도록 PATH를 제어하는 것이었습니다.각 툴을 가리키는 환경 변수를 생성한 다음 이들과 몇 가지 다른 툴을 기반으로 PATH를 계산했습니다.우리가 마침내 재현 가능한 빌드를 만들 때까지 유사한 기술이 다른 구성 가능한 설정을 길들였습니다.
그런데, Maven을 사용하지 마십시오. Java는 괜찮습니다. 그리고 WebLogic의 클러스터링이 꼭 필요한 경우에만 구입하십시오(그러나 그 외에는 필요하지 않습니다. 특히 독점적인 기능이 필요하지 않습니다).
행복을 빌며.
@litb와 마찬가지로, 저는 "셸 스크립트에서 $PATH 요소를 조작하는 방법"이라는 질문에 대한 답변을 제출했습니다. 그래서 저의 주요 답변은 거기에 있습니다.
'의 'bash그리고 다른 본 셸 파생물은 가장 깔끔하게 달성됩니다.$IFS필드 간 구분 기호예를 들어, 위치 인수를 설정하려면($1,$2...)를 PATH의 요소에 사용합니다.
set -- $(IFS=":"; echo "$PATH")
$PATH에 공백이 없으면 정상적으로 작동합니다.공백을 포함하는 경로 요소에 대해 작동하도록 하는 것은 중요하지 않은 연습입니다. 관심 있는 독자에게 남겨집니다.Perl과 같은 스크립트 언어를 사용하여 처리하는 것이 더 간단할 수 있습니다.
대본도 있고요.clnpath내 PATH를 설정하는 데 광범위하게 사용합니다."csh에서 PATH 변수가 중복되지 않도록 하는 방법"에 대한 답변에서 문서화했습니다.
이 문제를 성가시게 만드는 것은 첫 번째 요소와 마지막 요소 중 펜스 포스트 케이스입니다.IFS를 변경하고 배열을 사용하면 우아하게 문제를 해결할 수 있지만 경로가 배열 형태로 변환되면 콜론을 어떻게 다시 도입해야 할지 모르겠습니다.
다음은 하나의 디렉토리를 제거하는 약간 덜 우아한 버전입니다.$PATH문자열 조작만 사용합니다.시험해 봤습니다.
#!/bin/bash
#
# remove_from_path dirname
#
# removes $1 from user's $PATH
if [ $# -ne 1 ]; then
echo "Usage: $0 pathname" 1>&2; exit 1;
fi
delendum="$1"
NEWPATH=
xxx="$IFS"
IFS=":"
for i in $PATH ; do
IFS="$xxx"
case "$i" in
"$delendum") ;; # do nothing
*) [ -z "$NEWPATH" ] && NEWPATH="$i" || NEWPATH="$NEWPATH:$i" ;;
esac
done
PATH="$NEWPATH"
echo "$PATH"
Perl One-liner는 다음과 같습니다.
PATH=`perl -e '$a=shift;$_=$ENV{PATH};s#:$a(:)|^$a:|:$a$#$1#;print' /home/usr/bin`
그$a. 그s 및 (논의) 및print으로 명은암에작니다합동서에서 합니다.$_변수.
여기 좋은 것들.저는 애초에 술래를 추가하지 않기 위해 이것을 사용합니다.
#!/bin/bash
#
######################################################################################
#
# Allows a list of additions to PATH with no dupes
#
# Patch code below into your $HOME/.bashrc file or where it
# will be seen at login.
#
# Can also be made executable and run as-is.
#
######################################################################################
# add2path=($HOME/bin .) ## uncomment space separated list
if [ $add2path ]; then ## skip if list empty or commented out
for nodup in ${add2path[*]}
do
case $PATH in ## case block thanks to MIKE511
$nodup:* | *:$nodup:* | *:$nodup ) ;; ## if found, do nothing
*) PATH=$PATH:$nodup ## else, add it to end of PATH or
esac ## *) PATH=$nodup:$PATH prepend to front
done
export PATH
fi
## debug add2path
echo
echo " PATH == $PATH"
echo
확장 글로빙을 활성화하면 다음 작업을 수행할 수 있습니다.
# delete all /opt/local paths in PATH
shopt -s extglob
printf "%s\n" "${PATH}" | tr ':' '\n' | nl
printf "%s\n" "${PATH//+(\/opt\/local\/)+([^:])?(:)/}" | tr ':' '\n' | nl
man bash | less -p extglob
확장된 글로빙 원라이너(음, 일종의):
path_remove () { shopt -s extglob; PATH="${PATH//+(${1})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; }
1달러의 슬래시를 피할 필요는 없어 보입니다.
path_remove () { shopt -s extglob; declare escArg="${1//\//\\/}"; PATH="${PATH//+(${escArg})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; }
PATH에 콜론을 추가하면 다음과 같은 작업을 수행할 수 있습니다.
path_remove () {
declare i newPATH
# put a colon at the beginning & end AND double each colon in-between
newPATH=":${PATH//:/::}:"
for ((i=1; i<=${#@}; i++)); do
#echo ${@:${i}:1}
newPATH="${newPATH//:${@:${i}:1}:/}" # s/:\/fullpath://g
done
newPATH="${newPATH//::/:}"
newPATH="${newPATH#:}" # remove leading colon
newPATH="${newPATH%:}" # remove trailing colon
unset PATH
PATH="${newPATH}"
export PATH
return 0
}
path_remove_all () {
declare i newPATH extglobVar
extglobVar=0
# enable extended globbing if necessary
[[ ! $(shopt -q extglob) ]] && { shopt -s extglob; extglobVar=1; }
newPATH=":${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}" # s/:\/path[^:]*//g
done
newPATH="${newPATH#:}" # remove leading colon
newPATH="${newPATH%:}" # remove trailing colon
# disable extended globbing if it was enabled in this function
[[ $extglobVar -eq 1 ]] && shopt -u extglob
unset PATH
PATH="${newPATH}"
export PATH
return 0
}
path_remove /opt/local/bin /usr/local/bin
path_remove_all /opt/local /usr/local
path_remove_all(프록시 기준)에서:
-newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}"
+newPATH="${newPATH//:${@:${i}:1}*([^:])/}" # s/:\/path[^:]*//g
이 솔루션은 매우 오래된 스레드이지만 다음과 같이 흥미로울 수 있다고 생각했습니다.
PATH="/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
REMOVE="ccache" # whole or part of a path :)
export PATH=$(IFS=':';p=($PATH);unset IFS;p=(${p[@]%%$REMOVE});IFS=':';echo "${p[*]}";unset IFS)
echo $PATH # outputs /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
이 블로그 게시물에서 찾았습니다.저는 이것이 가장 마음에 드는 것 같아요 :)
저는 여기 있는 대부분의 사람들과는 약간 다른 접근 방식을 취했고 특히 다음과 같이 문자열 조작에만 집중했습니다.
path_remove () {
if [[ ":$PATH:" == *":$1:"* ]]; then
local dirs=":$PATH:"
dirs=${dirs/:$1:/:}
export PATH="$(__path_clean $dirs)"
fi
}
__path_clean () {
local dirs=${1%?}
echo ${dirs#?}
}
위는 제가 사용하는 최종 기능의 단순화된 예입니다.나는 또한 만들었습니다.path_add_before그리고.path_add_after이미 PATH에 지정된 경로 앞/뒤에 경로를 삽입할 수 있습니다.
전체 함수 집합은 my dotfiles의 path_helpers.sh에서 사용할 수 있습니다.PATH 문자열의 시작/중간/끝 부분에서 제거/추가/준비/삽입을 완전히 지원합니다.
언급URL : https://stackoverflow.com/questions/370047/what-is-the-most-elegant-way-to-remove-a-path-from-the-path-variable-in-bash
'codememo' 카테고리의 다른 글
| 옵션 매개 변수를 오버로드로 대체하는 것이 획기적인 변화입니까? (0) | 2023.05.18 |
|---|---|
| Mongoose 스키마에서 다른 스키마를 참조하는 방법은 무엇입니까? (0) | 2023.05.18 |
| VBA를 사용하여 Excel의 조건부 서식에서 배경색을 가져오는 방법 (0) | 2023.05.18 |
| Bash에서 명령어의 단일 따옴표 내 변수 확장 (0) | 2023.05.18 |
| 사용자 변수와 시스템 변수의 차이점은 무엇입니까? (0) | 2023.05.18 |