Bash에서 명령 대체를 포함하는 변수

Bash에서 명령 대체를 포함하는 변수

저는 bash(GNU bash, 버전 4.4.20(1)-release(i686-pc-linux-gnu))의 쉘 확장을 이해하려고 합니다.

내 대화형 bash 쉘 유형에서

x='$(id)'
$x
$(echo $x)

마지막 두 줄 중 하나에서 다음 형식의 오류가 발생할 것으로 예상됩니다.

bash: uid=xxx(user): command not found

하지만 얻었어

bash: $(id): command not found.

여기서 명령 대체가 왜 발생하지 않는지 이해가 되지 않습니다. 변수 확장을 통해 달성하면 안되는 걸까요? 내 생각엔 여기에 설명된 대로 Shell 작업과 관련이 있는 것 같습니다.https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Operation

누군가 이 동작을 설명할 수 있나요?

나는 bash 확장을 더 정확하게 이해하고 싶습니다. 내 질문에 실제 스크립트를 실행하는 데 관심이 없습니다.

답변1

$(…)명령 대체입니다("프로세스 대체" <(…)등). 변수 대체와 명령 대체는 문자열의 왼쪽에서 오른쪽으로 동일한 패스에서 발생합니다. 이러한 대체 결과로 발생하는 유일한 작업은 단어 분리기와 와일드카드입니다.

따라서 5자 문자열로 x='$(id)'설정하십시오 . 그런 다음 을 실행하기 위해 쉘은 값을 대체합니다 . 공백이나 와일드카드가 포함되어 있지 않으므로 명령 이름으로 처리됩니다.x$(id)$x$x$(id)

비교:

x='@(id)'
shopt -s extglob
echo /none/$x /usr/bin/$x

파일이 /none/id존재하지 않지만 /usr/bin/id존재한다고 가정하면 echo명령은 ( echo분명히), /none/@(id)(glob 패턴이 /none/@(id)아무것도 일치하지 않으므로 변경되지 않은 상태로 유지됨) 및 /usr/bin/id(glob 패턴이 /usr/bin/@(id)파일과 일치하므로 변경되지 않은 상태로 유지됨)의 세 단어로 확장됩니다. 일치하는 단일 요소 목록).

bash 매뉴얼에서 관련 문장은 다음과 같습니다.쉘 확장부분.

확장 순서는 중괄호 확장, 인수 및 변수 확장, 산술 확장, 명령 대체(왼쪽에서 오른쪽으로 수행)입니다.

두 세미콜론 사이의 모든 내용은 한 번에 전달됩니다. 각 패스는 이전 패스의 결과를 기반으로 합니다.

단 하나의 문장(위에서 인용한 문장만큼 복잡한 문장이라도)으로 전체 이야기를 전달할 수는 없습니다. 쉘 의미론은 복잡합니다. 나는 어떤 쉘의 매뉴얼에도 특별한 경우의 세부 사항이 모두 포함되어 있는지 의심스럽습니다. 이것POSIX 사양더 형식적이지만 bash 특정 확장을 다루지 않으며 심지어 매우 이상한 경우도 정의되지 않은 상태로 둡니다.

답변2

이것은 인용문입니다. 작은따옴표( ')는 리터럴 문자열을 정의하며 보간이나 이스케이프가 발생할 수 없습니다. 큰따옴표( ")는 보간 및 이스케이프를 허용합니다.

예는 다음과 같습니다.

$ x='$(id)'
$ echo 'The variable x contains the value \"$x\"'
The variable x contains the value \"$x\"
$ echo "The variable x contains the value \"$x\""
The variable x contains the value "$(id)"

$ x="$(id)"
$ echo "The variable x contains the value \"$x\""
The variable x contains the value "uid=1000(myusername)..."

다음은 작은따옴표와 큰따옴표를 기반으로 한 보간 및 이스케이프의 또 다른 예입니다.

$ echo 'The current directory is $PWD according to the variable \"\$PWD\".'
The current directory is $PWD according to the variable \"\$PWD\".

$ echo "The current directory is $PWD according to the variable \"\$PWD\"."
The current directory is /tmp according to the variable "$PWD".

관련 정보