eval을 사용하여 bash의 변수에 공백을 포함하는 값을 할당하는 방법 $(echo $var_name=$var_value) echo $fruit orange 그러나 변수

를 사용하여 변수에 값을 동적으로 할당하고 싶습니다 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입니다.

에서 bash4.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옵션을 추가 했지만 호출자가 함수 인 경우 호출자의 변수와 달리 전역 변수를 설정하기 때문에 원하는 것이 아닙니다 .declaresetvar

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(실제로 bashKorn 쉘의 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가 생성 된 후 해시 테이블에서 새 변수 가 즉시 제거됩니다.


답변