다음 대안들 사이에서 …
-
로
eval
.comd="ls" eval "$comd"
-
와
source /dev/stdin
printf "ls" | source /dev/stdin
-
과
source /dev/stdin
및( )
또는{ }
( printf "ls" ) | source /dev/stdin { printf "ls"; } | source /dev/stdin
(
printf
에서 실행할 때{ }
서브 쉘을 사용하지 않는 것 외에 다른 이점이 있습니까?)-
그들 사이의 차이점은 무엇입니까?
-
어느 것이 선호됩니까?
-
명령을 실행하기 위해 선호되는 방법은 무엇입니까?
()
또는{}
?
-
답변
- 방법의 차이점은 무엇입니까?
부터 bash manpage
:
eval [arg ...]
The args are read and concatenated together into a single com‐
mand. This command is then read and executed by the shell, and
its exit status is returned as the value of eval. If there are
no args, or only null arguments, eval returns 0.
source filename [arguments]
Read and execute commands from filename in the current shell
environment and return the exit status of the last command exe‐
cuted from filename. If filename does not contain a slash, file
names in PATH are used to find the directory containing file‐
name. The file searched for in PATH need not be executable.
When bash is not in posix mode, the current directory is
searched if no file is found in PATH. If the sourcepath option
to the shopt builtin command is turned off, the PATH is not
searched. If any arguments are supplied, they become the posi‐
tional parameters when filename is executed. Otherwise the
positional parameters are unchanged. The return status is the
status of the last command exited within the script (0 if no
commands are executed), and false if filename is not found or
cannot be read.
두 방법 사이에는 차이가 없습니다.
단 하나의 메모가 있습니다. eval
모든 인수를 연결 한 다음 단일 명령으로 실행됩니다. source
파일의 내용을 읽고 실행합니다. eval
인수가 아닌 명령 만 작성할 수 있습니다 stdin
. 따라서 다음과 같이 할 수 없습니다 :
printf "ls" | eval
- 어느 것이 더 선호됩니까?
귀하의 예는 동일한 결과를 제공하지만 목적 eval
과 source
는 다릅니다. source
일반적으로 다른 스크립트에 라이브러리를 제공하는 eval
데 사용되는 반면 명령 평가에만 사용됩니다. 회피 된 eval
끈이 깨끗하다는 보장이 없기 때문에 가능하면 사용을 피해야 합니다. 우리는 subshell
대신 에를 사용하여 위생 검사를 수행해야합니다 .
- () 또는 {}에서 일부 명령을 실행하면 어떤 것이 더 선호됩니까?
중괄호 안에서 시퀀스 명령을 실행하면 { }
모든 명령이 서브 쉘 대신 현재 쉘 에서 실행됩니다 (괄호 안에서 실행하는 경우 (bash 참조 )).
사용하면 subshell ( )
더 많은 리소스가 사용되지만 현재 환경에는 영향을 미치지 않습니다. 사용 { }
은 현재 쉘에서 모든 명령을 실행하므로 환경에 영향을줍니다. 목적에 따라 그중 하나를 선택할 수 있습니다.
답변
가장 큰 차이점은 두 번째와 세 번째 형식은 파이프를 사용한다는 것입니다. 이로 인해 bash는 서브 쉘에서 “source”명령을 강제 실행합니다 (lastpipe가 설정되어 있고 bash 4.2 이상에서만 사용 가능하지 않은 경우). :
printf "ls" | bash
결과적으로 코드에서 설정 한 환경 변수가 손실되므로 예상대로 작동하지 않습니다.
printf "abc=2" | source /dev/stdin
현재 쉘에서 명령을 실행하려면 프로세스 대체를 사용할 수 있습니다.
source <(printf "abc=2")
평소처럼 세미콜론을 사용하여 괄호 안에 더 많은 명령을 넣을 수 있습니다.
이 방법으로 파이프를 제거하면 “eval”과 “source”사용에 차이가 없다고 생각합니다. 특정한 경우에 사용하기 쉬운 것을 선호해야합니다.
- 변수에서 실행할 명령이 이미있는 경우 “eval”을 사용하십시오.
- 파일에 있거나 외부 명령에서 가져 오는 경우 “source”를 사용하십시오.
답변
이미 주어진 답변을 보완하기 위해 :
에 source
해당하는 …
comd="ls"
eval "$comd"
~는 ・ ・ ・
source <(printf ls)
ls
큰 차이가없는 경우 .
그러나 현재 환경 에 영향 을 미치는 명령 (일반적으로 사용 할 때 의도 한 source
것)의 경우이 변형은 (첫 번째 솔루션과 eval
마찬가지로) 수행하지만 두 번째 접근 방식은 하위 쉘의 환경에만 영향을 미칩니다. 코드를 실행 한 후에는 사용할 수 없습니다.