다음 옵션 사이에서...
그리고
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
실행할 때{ }
서브쉘을 사용하지 않는 것 외에 어떤 이점이 있습니까 ?)그들 사이의 차이점은 무엇입니까?
어느 것이 선호됩니까?
명령을 실행하는 데 선호되는 방법은 무엇입니까?
()
또는{}
?
답변1
다양한 방법의 차이점은 무엇입니까?
에서 man bash
:
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
명령 평가에만 사용됩니다. 'ed 문자열은 깨끗하다고 보장되지 않으므로 eval
가능하면 피해야 합니다 .eval
subshell
()
또는 에서 일부 명령을 실행하면{}
어느 것이 더 바람직합니까?
명령 시퀀스가 중괄호 안에 실행되면 { }
모든 명령이 실행됩니다.현재 쉘, 바꾸다서브쉘(이것은 괄호 안에 실행하면 발생합니다(bash 참조).인용하다)).
이를 사용하면 subshell ( )
더 많은 리소스가 필요하지만 현재 환경에는 영향을 미치지 않습니다. 를 사용하면 { }
현재 셸의 모든 명령이 실행되므로 환경이 영향을 받습니다. 어느 것을 선택하느냐는 목적에 따라 다릅니다.
답변2
주요 차이점은 두 번째와 세 번째 양식은 파이프를 사용한다는 것입니다. 그러면 bash가 서브셸에서 "source" 명령을 실행하게 됩니다(Lastpipe가 설정되지 않은 경우 bash 4.2+에서만 사용 가능). 이는 거의 다음과 같습니다.
printf "ls" | bash
결과적으로 코드에서 설정한 모든 환경 변수가 손실되므로 예상대로 작동하지 않습니다.
printf "abc=2" | source /dev/stdin
현재 셸에서 명령을 실행하려면 프로세스 대체를 사용할 수 있습니다.
source <(printf "abc=2")
평소와 같이 세미콜론을 사용하여 괄호 안에 더 많은 명령을 입력할 수 있습니다.
이런 식으로 파이프를 제거하면 "eval"과 "source"를 사용하는 것 사이에 차이가 없다고 생각합니다. 특별한 경우에는 더 간단한 것을 사용하는 것이 좋습니다.
- 변수에서 실행하려는 명령이 이미 있는 경우 "eval"을 사용하십시오.
- 파일에 넣거나 외부 명령에서 가져오는 경우 "source"를 사용하세요.
답변3
이미 제공된 답변에 추가로:
동등하다 source
...
comd="ls"
eval "$comd"
... 예...
source <(printf ls)
경우에는 ls
큰 차이가 없습니다 .
그러나 명령의 목적이 다음과 같다면현재 환경에 영향을 미침(코드 줄을 사용할 때 일반적으로 원하는 source
것은 eval
그 후에는 사용할 수 없습니다.
답변4
아직 이루어지지 않은 중요한 차이점이 있습니다!
❯ echo return | . /dev/stdin
❯ echo return | eval "$(cat -)"
sh: return: can only `return' from a function or sourced script
즉, return
스크립트를 소싱할 때만 작동합니다.
스크립트의 내용과 의도에 따라 어느 것을 선택하든 상관없겠지만 차이점은 지적할 가치가 있다고 생각합니다.
eval
위의 파이프 대신 파이프를 사용한 이유는 두 가지입니다 eval return
.
파이프를 통해 들어가는 것이 가능하다는 것을 증명하기 위해서입니다
eval
.일관성을 위해
source
so 및 둘 다eval
서브셸(파이프라인) 내에서 실행될 수 있습니다.예를 들어, 다음과 같이 시도한다면:
❯ echo a=1 | . /dev/stdin; echo $a ❯ echo a=1 | eval "$(cat -)"; echo $a
1
현재 환경에서 평가되지 않기 때문에 인쇄되지 않는 것을 알 수 있습니다 . 인쇄 하려면 다음을 수행해야 합니다1
.❯ echo a=1 | { . /dev/stdin; echo $a; } ❯ echo a=1 | { eval "$(cat -)"; echo $a; }