에서 이 질문에 누군가가 사용하여 문제를보고 여기에 문서를 내부 인용 구분 단어로 $(...)
명령 치환 백 슬래시, \
문서 트리거 내부의 줄의 끝에 줄 바꿈에 합류 행 계속이 여기에 같은 동안 문서 외부에서 예상대로 명령 치환 작업을 .
다음은 간단한 예제 문서입니다.
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 / 그 외) 중 하나에 의해 특정 처리가 표준에 의해 규정되어 있습니까? 금지? 허용?
답변
이것은 Bash의 메일 링리스트에서 물었고 , 관리자는 그것이 버그임을 확인했습니다.
또한 POSIX의 텍스트가 반드시 모호하지는 않지만 자세히 읽어야한다고 언급 했으므로 이에 대한 설명을 요청했습니다. 문제에 대한 설명과 표준의 해석을 포함한 답변 은 다음과 같습니다.
대체 명령은 붉은 청어입니다. 버그의 위치를 지적한 점에서만 관련이 있습니다.
here-document의 구분 기호가 인용되어 있으므로 행이 확장되지 않습니다. 이 경우, 쉘은 입력에서 인용 된 것처럼 행을 읽습니다. 백 슬래시가 인용 된 컨텍스트에 표시되면 이스케이프 문자로 작동하지 않으며 (아래 참조) 백 슬래시-줄 바꾸기를 특수하게 처리하지 않습니다. 실제로 구분 기호의 일부를 인용하면 여기에 문서 행이 작은 따옴표처럼 읽 힙니다.
Posix 2.2.1의 텍스트는 어색하게 작성되었지만 백 슬래시는 인용되지 않은 경우에만 특별히 처리됨을 의미합니다. 백 슬래시를 인용하고 작은 따옴표 또는 다른 백 슬래시로만 모든 확장을 금지 할 수 있습니다.
마지막 부분은 작은 따옴표를 의미하는 “확장되지 않은”텍스트입니다. 이 표준은 2.2에서 문서는 “또 다른 형태의 인용”이라고 말하지만, 단어가 전혀 확장되지 않는 유일한 인용 형태는 작은 따옴표입니다. 따라서 작은 따옴표가 아닌 작은 따옴표와 거의 같은 인용 형식입니다.