변수를 내보낸다고 가정해 보겠습니다.
foo=bar
export foo
이제 내보내기를 취소하고 싶습니다. 즉, 내가 이렇게 한다면 나는 그 환경 에 전혀 있을 sh -c 'echo "$foo"'
자격이 없습니다 bar
. 변수의 존재를 보여주는 간단한 방법의 예입니다. 명령은 무엇이든 될 수 있습니다. 명령의 동작은 해당 환경에 변수가 존재하는 경우에만 영향을 받을 수 있습니다.foo
sh -c
sh -c
저 할 수 있어요:
unset
변수를 만든 다음 잃습니다.env
제거하려면 각 명령을 사용하십시오.env -u foo sh -c 'echo "$foo"'
- 현재 셸을 한동안 계속 사용하려는 경우에는 이는 실용적이지 않습니다.
이상적으로는 변수의 값을 보존하고 싶지만 자식 프로세스에 빈 변수로 표시되지도 않고 표시되지도 않게 하고 싶습니다.
나는 이것을 할 수 있다고 생각합니다 :
otherfoo="$foo"; unset foo; foo="$otherfoo"; unset otherfoo
otherfoo
이미 있으면 밟힐 위험이 있습니다.
이것이 유일한 방법입니까? 표준적인 방법이 있나요?
답변1
표준적인 방법은 없습니다.
함수를 사용하면 임시 변수 사용을 피할 수 있습니다. 다음 함수는 설정되지 않은 변수를 설정되지 않은 상태로 유지하고 빈 변수를 비워 두는 역할을 담당합니다. 그러나 읽기 전용 또는 입력된 변수와 같은 셸의 특정 기능은 지원하지 않습니다.
unexport () {
while [ "$#" -ne 0 ]; do
eval "set -- \"\${$1}\" \"\${$1+set}\" \"\$@\""
if [ -n "$2" ]; then
unset "$3"
eval "$3=\$1"
fi
shift; shift; shift
done
}
unexport foo bar
ksh, bash 및 zsh에서는 .unexport 를 사용하여 변수 내보내기를 취소할 수 있습니다 typeset +x foo
. 이는 유형과 같은 특별한 속성을 유지하므로 사용하는 것이 좋습니다. typeset
기능이 내장된 모든 쉘에는 typeset +x
.
case $(LC_ALL=C type typeset 2>&1) in
typeset\ *\ builtin) unexport () { typeset +x -- "$@"; };;
*) unexport () { … };; # code above
esac
답변2
편집하다:bash
의견에서 지적한 대로 에만 해당됩니다 .
각 이름에서 속성을 제거 -n
하는 옵션입니다 export
. export
(바라보다 help export
.)
그래서을 위한 bash
,원하는 명령은 다음과 같습니다.export -n foo
답변3
비슷한 POSIX 함수를 작성했지만 이로 인해 임의 코드가 실행될 위험이 발생하지 않습니다.
unexport()
while case ${1##[0-9]*} in ### rule out leading numerics
(*[!_[:alnum:]]*|"") ### filter out bad|empty names
set "" ${1+"bad name: '$1'"} ### prep bad name error
return ${2+${1:?"$2"}} ### fail w/ above err or return
esac
do eval set '"$'"{$1+$1}"'" "$'"$1"'" "$'@\" ### $1 = ( $1+ ? $1 : "" )
eval "${1:+unset $1;$1=\$2;} shift 3" ### $$1 = ( $1:+ ? $2 : -- )
done
또한 제공하고자 하는 만큼 많은 매개변수를 처리합니다. 매개변수가 유효한 이름이지만 설정되지 않은 경우 자동으로 무시됩니다. 인수가 잘못된 이름이면 stderr에 쓰고 필요한 경우 중지하지만 명령줄에서 잘못된 이름 앞에 오는 유효한 이름은 계속 처리합니다.
나는 다른 방법을 생각했다. 나는 그것을 선호한다.
unexport()
while unset OPTARG; OPTIND=1 ### always work w/ $1
case ${1##[0-9]*} in ### same old same old
(*[!_[:alnum:]]*|"") ### goodname && $# > 0 || break
${1+"getopts"} : "$1" ### $# ? getopts : ":"
return ### getopts errored or ":" didnt
esac
do eval getopts :s: '"$1" -"${'"$1+s}-\$$1\""
eval unset "$1; ${OPTARG+$1=\${OPTARG}#-}"
shift
done
음, 이 두 가지 모두 동일한 기술을 많이 사용합니다. 기본적으로 쉘 변수가 설정되지 않은 경우 이에 대한 참조는 +
매개변수 확장을 통해 확장되지 않습니다. 그러나 설정된 경우 해당 값에 관계없이 매개변수는 다음과 같이 확장됩니다.${parameter+word}
으로 확장될 예정입니다.word
- 변수 값 대신. 따라서 쉘 변수 자체 검사 및 자체 교체가 성공합니다.
쟤넨 괜찮아자기실패. 맨 위 함수에서 잘못된 이름이 발견되면 들어가서 null을 $1
남깁니다 $2
. 왜냐하면 모든 인수가 처리되고 루프가 끝나면 $1
내가 하는 다음 일은 성공이거나 인수가 유효하지 않으면 쉘이 return
확장 되어 스크립트된 쉘을 종료 $2
하기 때문입니다. $1:?
작성하는 동안 대화형 셸로 다시 중단됩니다.word
표준 오류로.
두 번째 숙제를 하세요 getopts
. 오류 이름을 지정하지 않습니다. 대신 stderr에 표준 오류 메시지를 씁니다. 더 중요한 것은 arg의 값을 저장한다는 것입니다.$OPTARG
만약에매개변수는 먼저 컬렉션 변수의 이름입니다. 따라서 모든 작업이 완료되면 세트를 적절한 할당으로 확장 getopts
해야 합니다 .eval
OPTARG