에서 이 질문에 누군가가 사용하여 문제를보고 여기에 문서를 내부 인용 구분 단어로 $(...)
명령 치환 백 슬래시, \
문서 트리거 내부의 줄의 끝에 줄 바꿈에 합류 행 계속이 여기에 같은 동안 문서 외부에서 예상대로 명령 치환 작업을 .
다음은 간단한 예제 문서입니다.
cat <<'EOT'
abc ` def
ghi \
jkl
EOT
여기에는 줄 끝에 하나의 백틱과 하나의 백 슬래시가 포함됩니다. 구분 기호는 인용되므로 본문 내에서 확장이 발생하지 않습니다. 모든 Bourne-alikes에서 나는 이것이 내용을 그대로 출력한다는 것을 알 수 있습니다. 다음과 같이 동일한 문서를 명령 대체 안에 넣으면 :
x=$(cat <<'EOT'
abc ` def
ghi \
jkl
EOT
)
echo "$x"
더 이상 동일하게 동작하지 않습니다.
dash
,ash
,zsh
,ksh93
, 비지 박스ash
,mksh
그리고 SunOS의 5.10 POSIX는sh
모든 이전과 문서의 그대로 내용을 제공합니다.- Bash 3.2는 일치하지 않는 백틱에 대한 구문 오류를 제공합니다. 일치하는 백틱을 사용하여 내용을 명령으로 실행하려고 시도합니다.
- Bash 4.3은 "ghi"와 "jkl"을 한 줄로 접지 만 오류는 없습니다.
--posix
옵션 이 영향을 미치지 않습니다. Kusalananda 는pdksh
같은 방식으로 작동하는 (감사합니다!)라고 말합니다 .
원래 질문에서 나는 이것이 Bash 파서의 버그라고 말했다. 그렇습니까? [업데이트 : 예 ] POSIX의 관련 텍스트 (모두 셸 명령 언어 정의의 모든 텍스트)는 다음과 같습니다.
- §2.6.3 명령 대체 :
$ (command) 형식을 사용하면 여는 괄호 다음에 일치하는 닫는 괄호 뒤에있는 모든 문자가 명령을 구성합니다. 지정되지 않은 결과를 생성하는 리디렉션만으로 구성된 스크립트를 제외하고 유효한 쉘 스크립트를 command에 사용할 수 있습니다 .
- §2.7.4 여기 문서 :
단어의 일부 가 인용되는 경우, 단어 에 대한 인용 제거를 수행하여 구분 기호를 구성해야하며 여기에 문서 행을 확장하지 않아야합니다.
- §2.2.1 이스케이프 문자 (백 슬래시) :
<newline>이 <backslash>를 따르는 경우, 쉘은 이것을 줄 연속으로 해석해야합니다. 입력을 토큰으로 나누기 전에 <backslash>와 <newline>을 제거해야합니다.
- §2.3 토큰 인식 :
때 io_here 토큰 문법이 인식되었다 (참조 셸 문법 하나 이상의 바로 다음 다음 후속 라인) NEWLINE를 , 하나 이상의 현재 - 문서의 본문을 형성 토큰의 규칙에 따라 해석되어야한다 여기 - 문서 .
io_here를 처리하지 않을 경우, 쉘은 아래의 첫 번째 적용 가능한 규칙을 입력의 다음 문자에 적용하여 입력을 토큰으로 분리합니다. ...
...
- 현재 문자가 <backslash>, 작은 따옴표 또는 큰 따옴표이고 인용되지 않은 경우 인용 된 텍스트의 끝까지 후속 문자의 인용에 영향을 미칩니다. 인용에 대한 규칙은에 설명되어 있습니다 인용 . 토큰을 인식하는 동안 대체는 실제로 수행되지 않으며 결과 토큰에는 입력에 표시되는 문자 (<newline> joining 제외)가 포함되거나 닫히는 따옴표 나 대체 연산자를 포함하여 수정되지 않은 문자가 포함됩니다. 인용 텍스트의.
이것에 대한 나의 해석은 $(
종료하기 전까지의 모든 문자 )
가 셸 스크립트, 그대로를 구성한다는 것입니다. here 문서가 나타나므로 일반적인 토큰 화 대신 here 문서 처리가 수행됩니다. here 문서는 인용 된 구분 기호를 가지며, 그 내용은 그대로 처리됩니다. 이스케이프 캐릭터는 절대 들어오지 않습니다. 그러나이 사례는 단순히 해결되지 않았으며 두 가지 행동 모두 허용된다는 주장을 볼 수 있습니다. 어딘가에서 관련 텍스트를 건너 뛸 수도 있습니다.
- 이 상황이 다른 곳에서 더 명확 해 집니까?
- 이식 가능한 스크립트는 이론적으로 무엇에 의존해야합니까?
- 이 포탄 (Bash 3.2 / Bash 4.3 / 그 외) 중 하나에 의해 특정 처리가 표준에 의해 규정되어 있습니까? 금지? 허용?
echo "$x"
이지만 변수를 검사하는 모든 방법이 작동합니다. 그 줄을 맨 아래로 편집했습니다.
$(...)
그 출력이 무엇이든 대체합니다 . 이제 서브 쉘에서 예제에서 명령을 실행할 때 bash
예상 된 결과가 출력됩니다. "ghi"및 "jkl"을 축소하는 명령 대체로 전환 할 때만 가능합니다. 이것은 버그 imo입니다