$path
다음 코드 조각에 표시된 것보다 배열의 로컬 버전을 설정하는 데 덜 힘든 방법이 있습니까 ?
foo () {
local holdpath
holdpath=($path)
local path
path=($holdpath)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
구체적으로 카바레 쇼를 말하는 것인데 holdpath
…
내가 정의한다면
foo () {
local path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
...첫 번째 할당으로 인해 오류가 path
발생했습니다 . bad pattern
물론 내가 정의한다면
foo () {
local path
path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
...첫 번째 할당은 path
아무런 차이가 없습니다(즉, 결과를 변경하지 않고 생략할 수 있음). 할당이 있든 없든 $path
비어 있습니다.
편집하다:
다음 스크립트는 지금까지 받은 다양한 제안을 테스트합니다.
foo_0 () {
echo ${#path}
local PATH=$PATH
echo ${#path}
}
foo_1 () {
echo ${#path}
eval "local path; path=(${(q)path})"
echo ${#path}
}
foo_2 () {
echo ${#path}
eval "$(local -p path)"
echo ${#path}
}
for i ( 0 1 2 ) {
fn=foo_$i
echo "# $fn"
$fn
echo
}
출력은 다음과 같습니다
# foo_0
22
22
# foo_1
22
1
# foo_2
22
22
foo_0
따라서 및 의 출력은 foo_2
적어도 제가 달성하려는 것과 일치합니다. 위에 주어진 것처럼 작동하지 않는 것들이 있지만 할당하는 동안 foo_1
제거했습니다 .(q)
path
foo_1 () {
echo ${#path}
eval "local path; path=($path)"
echo ${#path}
}
foo_0
...그러면 출력은 및 의 출력과 일치합니다 foo_2
. 불행하게도 한정자의 문서를 몇 번 읽어도 q
원래 레시피에서 어떤 역할을 하는지 잘 이해가 되지 않습니다.
또한 다음 명령줄 변형이 foo_0
위의 변형과 다른 이유를 이해할 수 없습니다.
% (foo_0a () { echo ${#path}; local PATH=$PATH; echo ${#path} }; foo_0a)
22
1
해당 명령줄 변형인 FWIW는 foo_1
스크립트 foo_2
의 원본과 동일한 결과를 생성합니다.
% (foo_1a () { echo ${#path}; eval "local path; path=(${(q)path})"; echo ${#path} }; foo_1a)
22
1
% (foo_2a () { echo ${#path}; eval "$(local -p path)"; echo ${#path}; }; foo_2a)
22
22
또한 위의 모든 경우에서 원인 보다는 echo ${#path}
결과는 지역 변수에 공백으로 구분된 단일 문자열의 모든 개별 경로가 포함되어 있다는 것입니다.1
22
$path
답변1
PATH
배열 대신 스칼라 형식을 사용하십시오 path
. 둘 중 하나를 만들면 둘 다 효과적으로 현지화됩니다. 따라서 다음과 같습니다.
foo() {
local PATH=$PATH
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
(일부 경로 구성 요소가 포함된 경우에는 작동하지 않습니다 :
.)
안타깝게도 로컬 배열 매개변수는 명령문에서 초기화할 수 없으므로 원래 값으로 초기화할 수 없습니다.
답변2
그리고묶음배열을 사용할 수 있습니다리치의 대답, 일반적으로 다음과 같이 할 수 있습니다.
foo() {
eval "local array; array=(${(q)array[@]})"
...
}
이는 (q)
배열 요소에 대한 참조입니다. 예를 들어 와 같은 값의 경우 로 $PATH
확장 됩니다 . 문자열이 에 전달되므로 이러한 공백과 달러 문자를 이스케이프해야 합니다 ./foo bar:/x$y
"${(q)path[@]}"
/foo\ bar /x\$y
eval
다음과 같이 할 수도 있습니다.
foo() {
eval "$(local -p array)"
...
}
모든 유형의 변수에서 작동하지만 이로 인해 추가 프로세스가 생성됩니다.