다음 스크립트가 예상대로 작동하는 이유는 무엇입니까(인쇄 hello
)
#!/bin/bash
foo=$(bash -c 'echo hello')
echo $foo
그리고 이 스크립트는:
#!/bin/bash
cmd="bash -c 'echo hello'"
foo=$($cmd)
echo $foo
다음과 같은 오류가 발생합니다.
hello': -c: line 0: unexpected EOF while looking for matching `''
hello': -c: line 1: syntax error: unexpected end of file
답변1
존재하다,
cmd="bash -c 'echo hello'"
$cmd
당신이 실행하고 있는 것은 bash -c 'echo hello'
명령 이 아니라 $cmd
간단한 명령입니다.
인용 해제는 $cmd
Split+glob 연산자를 호출하는 것을 의미합니다. 여기서는 기본값을 사용하여 $IFS
의 내용을 , , 로 $cmd
분할합니다 . 따라서 다음과 같이 입력한 것처럼 이 4개의 매개변수를 사용하여 실행하고 있습니다.bash
-c
'echo
hello'
bash
bash -c "'echo" "hello'"
코드 'echo
에 닫는 따옴표가 없습니다( 매개변수가 이 인라인 스크립트 hello'
에 들어감 ).$0
$cmd
쉘 코드의 내용을 평가하고 싶다면,
eval "$cmd"
그래서:
cmd="bash -c 'echo hello'"
foo=$(eval "$cmd")
echo "$foo"
Split+glob 연산자를 다른 방법으로 사용할 수도 있습니다.
cmd='bash,-c,echo hello'
IFS=, # split on comma
set -f # disable glob
foo=$($cmd)
echo "$foo"
답변2
내부에서 실행되는 내용을 살펴보겠습니다 $($cmd)
.
$ cmd="bash -c 'echo hello'"
$ foo=$(printf '<%s>' $cmd)
$ echo "$foo"
<bash> <-c> <'echo> <hello'>
보시다시피 실행된 명령줄은 다음과 같습니다.
$ foo=$( "bash" "-c" "'echo" "hello'")
표현식의 한쪽에는 "'echo"
실행할 명령으로 구문 분석되는 작은따옴표가 있으며 bash -c
닫는 작은따옴표가 누락되었음을 (올바르게) 보고합니다.`''
한 가지 해결책은 eval을 사용하여 명령의 올바른 구문 분석을 용이하게 하는 것입니다.
$ foo=$(eval "printf '<%s>' $cmd"); echo "$foo"
<bash><-c><echo hello>
이것은 작동합니다:
$ foo=$(eval "$cmd"); echo "$foo"
hello
그러나 올바른 생각은 다음과 같습니다."변수는 데이터를 저장하고, 함수는 코드를 저장합니다".
$ cmd(){ bash -c 'echo hello'; }
$ foo=$(cmd); echo "$foo"
hello