명령 대체를 포함하는 bash의 변수

명령 대체를 포함하는 bash의 변수

Bash(GNU bash, 버전 4.4.20(1)-릴리스(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자 string 으로 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)하나의 파일과 일치하므로 다음으로 대체됩니다. 요소가 1개인 일치 항목 목록).

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".

관련 정보