나는 이것을 우연히 발견했습니다. 요약하면 이 예는 다음과 같습니다.
/ # a=$(eval echo hello world)
/ # echo $a
hello world
/ # $(eval echo hello world)
/bin/sh: hello: not found
/ # a=$(hello world)
/bin/sh: hello: not found
hello world
첫 번째 줄이 괄호 안에 확장되고 마지막 줄과 같은 방식으로 확장되기를 원합니다 a=$(hello world)
. 결국 help eval
그것은 우리에게 다음과 같이 말합니다.
ARG를 단일 문자열로 결합하고 결과를 셸에 대한 입력으로 사용하고 결과 명령을 실행합니다.
eval이 언롤링 전에 결과 명령을 실행하는 경우 $()
(예상) 결과는 hello world
실행할 수 없다는 오류가 발생해야 합니다(실제 명령이 없는 경우 hello
).
왜 a=$(eval echo hello world)
예상대로 오류가 발생하지 않았습니다.?
답변1
$()가 확장되기 전에 eval이 결과 명령을 실행하는 경우(예상한 대로) 결과는 오류가 되어야 합니다. 왜냐하면 hello world는 실행 가능하지 않기 때문입니다(실제 hello 명령이 없는 한).
이것은 대안이 작동하는 방식이 아닙니다. 단순한 존재로 $(..)
인해 발생 eval
하거나 심지어 실행됩니다.
첫 번째,$(..)
명령 대체Bash에서는 괄호 안에 실행된 명령의 출력을 캡처하여 변수에 저장하는 방법입니다. $(..)
그 안에 있는 콘텐츠로 대체되는 출력
이 부분은
a=$(eval echo hello world)
다음 순서로 쉘에 의해 실행됩니다. 실행 은eval echo hello world
echo 명령을 실행하고 변수에 저장된 문자열을 출력하는 것만큼 간단합니다echo hello world
.hello world
a
부품은 1)에 설명된 대로 반환됩니다
$(eval echo hello world)
. 그러나 어디에서나 출력을hello world
캡처할 할당이 없습니다 .$(..)
따라서 리터럴 문자열이 셸에 반환됩니다hello world
. 쉘은 이를 명령(리터럴hello
문자열)으로 해석하려고 시도합니다. 따라서 해당 이름의 명령을 찾을 수 없다는 오류가 표시됩니다.같은 일이
a=$(hello world)
일어납니다. 1)에서 언급했듯이 이 섹션에서는$(..)
괄호 안의 내용을 명령으로 실행합니다. 따라서 리터럴 문자열을 다시 계산하면 동일한 오류가 발생합니다.
2) 및 3)의 경우 $(..)
확장 시 따옴표가 없는 리터럴 문자열이 hello world
셸로 반환되어 토큰화가 발생 hello
하고 world
두 개의 별도 단어로 표시됩니다. 이것이 hello
전체 문자열 대신 명령으로 실행되는 동안 오류가 발생하는 이유입니다 hello world
.
eval
Even처럼 간단한 명령을 사용할 때는 주의하세요 echo
. 올바르게 호출되지 않으면 위험한 명령이 실행될 위험이 있습니다. 바라보다항상 사용해도 안전합니까 eval echo
?