를 사용하여 변수에 값을 동적으로 할당하고 싶습니다 eval
. 다음 더미 예제가 작동합니다.
var_name="fruit"
var_value="orange"
eval $(echo $var_name=$var_value)
echo $fruit
orange
그러나 변수 값에 공백이 포함되어 eval
있으면 $var_value
큰 따옴표로 묶어 도 오류가 반환됩니다 .
var_name="fruit"
var_value="blue orange"
eval $(echo $var_name="$var_value")
bash: orange : command not found
이것을 우회하는 방법은 무엇입니까?
답변
평가를 사용하지 말고 사용하십시오. declare
$ declare "$var_name=$var_value"
$ echo "fruit: >$fruit<"
fruit: >blue orange<
답변
eval
이것을 위해 사용하지 마십시오 . 사용하십시오 declare
.
var_name="fruit"
var_value="blue orange"
declare "$var_name=$var_value"
단어 분리는 문제가되지 않습니다. 왜냐하면 그 다음에 오는 모든 것이 첫 단어 만이 아니라의 =
값으로 취급 되기 때문 declare
입니다.
에서 bash
4.3라는 이름의 참고 문헌이 조금 더 간단합니다.
$ declare -n var_name=fruit
$ var_name="blue orange"
$ echo $fruit
blue orange
당신 은eval
일을 할 수 있지만 여전히해서는 안됩니다 🙂 사용 eval
하는 것은 나쁜 습관입니다.
$ eval "$(printf "%q=%q" "$var_name" "$var_value")"
답변
작업하기에 좋은 방법 은 테스트 용 eval
으로 교체하는 것입니다 echo
. echo
그리고 eval
(우리는 따로 설정하면 같은 일을 \x
일부 수행 확장 echo
등의 구현 bash
‘어떤 조건들).
두 명령 모두 사이에 하나의 공백으로 인수를 결합합니다. 차이점은 결과를 쉘 코드로 평가 / 해석 하는 동안 결과 를 echo
표시 한다는 것입니다.eval
그래서 어떤 쉘 코드를 보려고
eval $(echo $var_name=$var_value)
평가하면 다음을 실행할 수 있습니다.
$ echo $(echo $var_name=$var_value)
fruit=blue orange
그것은 당신이 원하는 것이 아니라 원하는 것입니다.
fruit=$var_value
또한 $(echo ...)
여기를 사용하는 것은 의미가 없습니다.
위를 출력하려면 다음을 실행하십시오.
$ echo "$var_name=\$var_value"
fruit=$var_value
따라서 해석하기 위해 간단히 다음과 같습니다.
eval "$var_name=\$var_value"
개별 배열 요소를 설정하는 데에도 사용할 수 있습니다.
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
다른 사람들이 말했듯이 코드를 bash
구체적으로 신경 쓰지 않으면 다음 declare
과 같이 사용할 수 있습니다 .
declare "$var_name=$var_value"
그러나 부작용이 있습니다.
변수의 범위를 변수가 실행되는 함수로 제한합니다. 따라서 다음과 같은 경우에는 변수를 사용할 수 없습니다.
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
그것이 foo
지역 변수를 선언 setvar
하므로 쓸모가 없습니다.
bash-4.2
전역 변수 를 선언 하는 -g
옵션을 추가 했지만 호출자가 함수 인 경우 호출자의 변수와 달리 전역 변수를 설정하기 때문에 원하는 것이 아닙니다 .declare
setvar
setvar() {
var_name=$1 var_value=$2
declare -g "$var_name=$var_value"
}
foo() {
local myvar
setvar myvar 'some value'
echo "1: $myvar"
}
foo
echo "2: $myvar"
어떤 출력 :
1:
2: some value
또한 변수가 이미 설정된 경우 declare
호출 되는 동안 declare
(실제로 bash
Korn 쉘의 typeset
내장 에서 개념을 빌린 ) declare
새 변수를 선언하지 않으며 할당 방법은 변수 유형에 따라 다릅니다.
예를 들어 :
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
varname
이전에 스칼라 , 배열 또는 연관 배열 로 선언 된 경우 다른 결과가 생성 될 수 있습니다 (그리고 잠재적으로 불쾌한 부작용이 발생할 수 있음) .
답변
당신이 할 경우 :
eval "$name=\$val"
… 그리고 쉘이 간단한 명령을 구분하는 것으로 해석 할 수 $name
있는 ;
-또는 다른 여러 토큰을 포함합니다 -적절한 쉘 구문이 앞에옵니다.
name='echo hi;varname' val='be careful with eval'
eval "$name=\$val" && echo "$varname"
산출
hi
be careful with eval
그러나 때때로 그러한 진술의 평가와 실행을 분리하는 것이 가능할 수 있습니다. 예를 들어 alias
명령을 사전 평가하는 데 사용할 수 있습니다. 다음 예에서 변수 정의 는 평가 alias
중인 $nm
변수에 ASCII 영숫자 또는와 일치하지 않는 바이트가 포함되어 있지 않은 경우에만 선언 될 수 있는 변수 정의에 저장됩니다 _
.
LC_OLD=$LC_ALL LC_ALL=C
alias "${nm##*[!_A-Z0-9a-z]*}=_$nm=\$val" &&
eval "${nm##[0-9]*}" && unalias "$nm"
LC_ALL=$LC_OLD
eval
여기 alias
에서 varname 에서 새 호출을 처리하는 데 사용됩니다 . 그러나 이전 alias
정의가 성공한 경우에만 호출됩니다 . 많은 다른 구현에서 alias
이름에 대해 다른 종류의 값을 받아 들일 것이라는 것을 알고 있지만 완전히 빈 값을 허용하는 값으로 아직 실행되지 않았습니다. .
그러나의 정의 alias
는에 대한 _$nm
것이며 이는 중요한 환경 값을 덮어 쓰지 않도록하기위한 것입니다. 나는 a로 시작하는 주목할만한 환경 값을 알지 못하며 _
일반적으로 semi-private 선언에 대한 안전한 내기입니다.
어쨌든, alias
정의가 성공하면 의 값에 대해 alias
명명 된 이름을 선언합니다 $nm
. 그리고 숫자로 시작하지 않으면 eval
전화 할 alias
것입니다.eval
에만 널 인수를 가져옵니다. 따라서 두 조건이 모두 충족 eval
되면 별칭이 호출되고 별칭에 저장된 변수 정의 alias
가 생성 된 후 해시 테이블에서 새 변수 가 즉시 제거됩니다.