a=$(eval echo hello world)가 왜 잘못되지 않나요?

a=$(eval echo hello world)가 왜 잘못되지 않나요?

나는 이것을 우연히 발견했습니다. 요약하면 이 예는 다음과 같습니다.

/ # 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에서는 괄호 안에 실행된 명령의 출력을 캡처하여 변수에 저장하는 방법입니다. $(..)그 안에 있는 콘텐츠로 대체되는 출력

  1. 이 부분은 a=$(eval echo hello world)다음 순서로 쉘에 의해 실행됩니다. 실행 은 eval echo hello worldecho 명령을 실행하고 변수에 저장된 문자열을 출력하는 것만큼 간단합니다 echo hello world.hello worlda

  2. 부품은 1)에 설명된 대로 반환됩니다 $(eval echo hello world). 그러나 어디에서나 출력을 hello world캡처할 할당이 없습니다 . $(..)따라서 리터럴 문자열이 셸에 반환됩니다 hello world. 쉘은 이를 명령(리터럴 hello문자열)으로 해석하려고 시도합니다. 따라서 해당 이름의 명령을 찾을 수 없다는 오류가 표시됩니다.

  3. 같은 일이 a=$(hello world)일어납니다. 1)에서 언급했듯이 이 섹션에서는 $(..)괄호 안의 내용을 명령으로 실행합니다. 따라서 리터럴 문자열을 다시 계산하면 동일한 오류가 발생합니다.

2) 및 3)의 경우 $(..)확장 시 따옴표가 없는 리터럴 문자열이 hello world셸로 반환되어 토큰화가 발생 hello하고 world두 개의 별도 단어로 표시됩니다. 이것이 hello전체 문자열 대신 명령으로 실행되는 동안 오류가 발생하는 이유입니다 hello world.


evalEven처럼 간단한 명령을 사용할 때는 주의하세요 echo. 올바르게 호출되지 않으면 위험한 명령이 실행될 위험이 있습니다. 바라보다항상 사용해도 안전합니까 eval echo?

관련 정보