서브셸의 bash -c에서 EOF 구문 분석 오류 발생

서브셸의 bash -c에서 EOF 구문 분석 오류 발생

다음 스크립트가 예상대로 작동하는 이유는 무엇입니까(인쇄 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간단한 명령입니다.

인용 해제는 $cmdSplit+glob 연산자를 호출하는 것을 의미합니다. 여기서는 기본값을 사용하여 $IFS의 내용을 , , 로 $cmd분할합니다 . 따라서 다음과 같이 입력한 것처럼 이 4개의 매개변수를 사용하여 실행하고 있습니다.bash-c'echohello'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

관련 정보