업데이트 : 어떤 사람들은 eval을 사용해서는 안된다고 말합니다. 동의하지 않습니다. 손상된 입력을에 전달할 수있을 때 위험이 발생한다고 생각합니다 eval
. 그러나 위험하지 않은 많은 일반적인 상황이 있으므로 어떤 경우에도 eval을 사용하는 방법을 아는 것이 좋습니다. 이 stackoverflow 답변 은 평가의 위험과 평가의 대안을 설명합니다. 평가가 안전하고 효율적인지 여부를 결정하는 것은 궁극적으로 사용자의 몫입니다.
bash eval
문을 사용하면 bash 스크립트로 계산하거나 얻은 코드 줄을 실행할 수 있습니다.
아마도 가장 간단한 예는 다른 bash 스크립트를 텍스트 파일로 열고 각 텍스트 줄을 읽고 eval
순서대로 실행 하는 bash 프로그램 일 것입니다. 그것은 bash와 본질적으로 동일한 동작입니다.source
가져온 스크립트의 내용에 대해 어떤 종류의 변환 (예 : 필터링 또는 대체)을 수행 할 필요가없는 한 문과 입니다.
나는 거의 필요하지 않지만 다른 변수에 할당 된 문자열에 이름 이 포함 된 eval
변수를 읽거나 쓰는 것이 유용하다는 것을 알았습니다 . 예를 들어, 코드 풋 프린트를 작게 유지하면서 중복성을 피하면서 변수 세트에 대한 조치를 수행합니다.
eval
개념적으로 간단합니다. 그러나 bash 언어의 엄격한 구문과 bash 인터프리터의 구문 분석 순서는 미묘한 차이가 있으며 eval
암호로 보이며 사용하기 어렵거나 이해하기 어렵습니다. 필수 사항은 다음과 같습니다.
전달 된 인수 는 런타임에 계산 eval
되는 문자열 표현식 입니다. eval
인수의 최종 구문 분석 결과를 스크립트 의 실제 코드 줄로 실행합니다 .
구문 및 구문 분석 순서는 엄격합니다. 결과가 스크립트 범위에서 실행 가능한 bash 코드 행이 아닌 경우 프로그램은 eval
가비지를 실행하려고 할 때 명령문에서 충돌 합니다.
테스트 할 때 eval
명령문을 바꾸고 echo
표시되는 것을 볼 수 있습니다 . 현재 컨텍스트에서 합법적 인 코드이면 코드를 실행하는 것이 eval
좋습니다.
다음 예제는 eval의 작동 방식을 명확히하는 데 도움이 될 수 있습니다 ...
예 1 :
eval
'정상적인'코드 앞에있는 진술은 NOP
$ eval a=b
$ eval echo $a
b
위의 예에서 첫 번째 eval
진술은 목적이 없으며 제거 할 수 있습니다. eval
코드에 대한 동적 측면이 없기 때문에 첫 번째 행에서 의미가 없습니다. 즉, 이미 bash 코드의 마지막 행으로 구문 분석되었으므로 bash 스크립트의 일반 코드 명령문과 동일합니다. 두 번째도 의미 eval
가 없습니다. 왜냐하면 구문 분석 단계 $a
가 문자 그대로의 문자열 로 변환 되기는하지만 간접적 인 것은 없습니다 (예 : 실제 bash 명사 또는 bash-held 스크립트 변수 의 문자열 값을 통한 참조 없음 ). eval
접두사가 없는 코드 줄로 .
예 2 :
문자열 값으로 전달 된 var 이름을 사용하여 var 할당을 수행하십시오.
$ key="mykey"
$ val="myval"
$ eval $key=$val
$ echo $mykey
myval
에 있었다면 echo $key=$val
출력은 다음과 같습니다.
mykey=myval
즉 , 문자열 구문 분석의 최종 결과는 eval에 의해 실행될 것이므로 결국 echo 문의 결과는 ...
예 3 :
예 2에 더 많은 간접 추가
$ keyA="keyB"
$ valA="valB"
$ keyB="that"
$ valB="amazing"
$ eval eval \$$keyA=\$$valA
$ echo $that
amazing
위의 예제는 앞의 예제보다 약간 더 복잡하여 bash의 구문 분석 순서와 특성에 더 크게 의존합니다. eval
라인은 대략 다음과 같은 순서로 내부적으로 분석 얻을 것이다 (다음 문 그냥 문이 최종 결과에 도달하기 위해 내부적으로 단계로 나누어받을 것입니다 방법을 보여 시도, 의사가 아닌 실제 코드이다 참고) .
eval eval \$$keyA=\$$valA # substitution of $keyA and $valA by interpreter
eval eval \$keyB=\$valB # convert '$' + name-strings to real vars by eval
eval $keyB=$valB # substitution of $keyB and $valB by interpreter
eval that=amazing # execute string literal 'that=amazing' by eval
가정 된 구문 분석 순서가 어떤 평가가 충분한 지 설명하지 못하면, 세 번째 예는 구문 분석을 더 자세히 설명하여 진행 상황을 명확하게 설명 할 수 있습니다.
예 4 :
이름 이 문자열에 포함 된 var 자체에 문자열 값이 포함되어 있는지 확인하십시오 .
a="User-provided"
b="Another user-provided optional value"
c=""
myvarname_a="a"
myvarname_b="b"
myvarname_c="c"
for varname in "myvarname_a" "myvarname_b" "myvarname_c"; do
eval varval=\$$varname
if [ -z "$varval" ]; then
read -p "$varname? " $varname
fi
done
첫 번째 반복에서 :
varname="myvarname_a"
배쉬의 인수를 구문 분석 eval
하고, eval
실행시 문자 그대로이보고 :
eval varval=\$$myvarname_a
다음 의사 코드 는 bash가 위의 실제 코드 줄을 해석하여에 의해 실행되는 최종 값에 도달 하는 방법 을 보여 줍니다 . (다음 줄은 정확한 bash 코드가 아니라 설명 적입니다) :eval
1. eval varval="\$" + "$varname" # This substitution resolved in eval statement
2. .................. "$myvarname_a" # $myvarname_a previously resolved by for-loop
3. .................. "a" # ... to this value
4. eval "varval=$a" # This requires one more parsing step
5. eval varval="User-provided" # Final result of parsing (eval executes this)
모든 파싱이 완료되면 결과가 실행되고 그 효과가 분명해 eval
지며, 그 자체에 대해 특별히 신비한 것이 없음을 나타내며, 인수 의 파싱 에 복잡성이 있습니다.
varval="User-provided"
위 예제의 나머지 코드는 단순히 $ varval에 할당 된 값이 null인지 확인하여 값을 제공하라는 메시지를 표시합니다.
$($n)
실행됩니다$n
.1
존재하지 않는 명령을 실행하려고 시도 합니다.