POSIX는 여기에 인용 된 명령 대체 문서에 무엇이 필요합니까?


20

에서 이 질문에 누군가가 사용하여 문제를보고 여기에 문서를 내부 인용 구분 단어로 $(...)명령 치환 백 슬래시, \문서 트리거 내부의 줄의 끝에 줄 바꿈에 합류 행 계속이 여기에 같은 동안 문서 외부에서 예상대로 명령 치환 작업을 .

다음은 간단한 예제 문서입니다.

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를 처리하지 않을 경우, 쉘은 아래의 첫 번째 적용 가능한 규칙을 입력의 다음 문자에 적용하여 입력을 토큰으로 분리합니다. ...

    ...

    1. 현재 문자가 <backslash>, 작은 따옴표 또는 큰 따옴표이고 인용되지 않은 경우 인용 된 텍스트의 끝까지 후속 문자의 인용에 영향을 미칩니다. 인용에 대한 규칙은에 설명되어 있습니다 인용 . 토큰을 인식하는 동안 대체는 실제로 수행되지 않으며 결과 토큰에는 입력에 표시되는 문자 (<newline> joining 제외)가 포함되거나 닫히는 따옴표 나 대체 연산자를 포함하여 수정되지 않은 문자가 포함됩니다. 인용 텍스트의.

이것에 대한 나의 해석은 $(종료하기 전까지의 모든 문자 )가 셸 스크립트, 그대로를 구성한다는 것입니다. here 문서가 나타나므로 일반적인 토큰 화 대신 here 문서 처리가 수행됩니다. here 문서는 인용 된 구분 기호를 가지며, 그 내용은 그대로 처리됩니다. 이스케이프 캐릭터는 절대 들어오지 않습니다. 그러나이 사례는 단순히 해결되지 않았으며 두 가지 행동 모두 허용된다는 주장을 볼 수 있습니다. 어딘가에서 관련 텍스트를 건너 뛸 수도 있습니다.


  • 이 상황이 다른 곳에서 더 명확 해 집니까?
  • 이식 가능한 스크립트는 이론적으로 무엇에 의존해야합니까?
  • 이 포탄 (Bash 3.2 / Bash 4.3 / 그 외) 중 하나에 의해 특정 처리가 표준에 의해 규정되어 있습니까? 금지? 허용?

두 번째 경우에 어떻게 출력물을 생산하는지 보여줄 수 있습니까?
Julie Pelletier

@JuliePelletier echo "$x"이지만 변수를 검사하는 모든 방법이 작동합니다. 그 줄을 맨 아래로 편집했습니다.
Michael Homer

2
쉬운 수정 인 것 같습니다. 이 패치는 최소한 작동하는 것 같습니다 : ignore_quoted_newline_in_quoted_heredoc.patch
geirha

1
"부셸은 [...] 하위 쉘 환경에서 명령을 실행하고 명령 대체 [...]를 표준 출력으로 대체하여 명령 대체를 확장해야하기 때문에이 표준을 올바르게 해석하고 있으며 표준이 매우 명확하다고 생각합니다 . "...]" 명령은 서브 쉘에서 명령을 실행하고 $(...)그 출력이 무엇이든 대체합니다 . 이제 서브 쉘에서 예제에서 명령을 실행할 때 bash예상 된 결과가 출력됩니다. "ghi"및 "jkl"을 축소하는 명령 대체로 전환 할 때만 가능합니다. 이것은 버그 imo입니다
don_crissti

2
@geirha 나는 Bash 버그를 보고했다 . pdksh는 현재 유지 관리의 그림자조차 가지고 있지 않기 때문에 pdksh에 대해 신경 쓰지 않을 것입니다.
Michael Homer

답변:


5

이것은 Bash의 메일 링리스트에서 물었고 , 관리자는 그것이 버그임을 확인했습니다.

또한 POSIX의 텍스트가 반드시 모호하지는 않지만 자세히 읽어야한다고 언급 했으므로 이에 대한 설명을 요청했습니다. 문제에 대한 설명과 표준의 해석을 포함한 답변 은 다음과 같습니다.

대체 명령은 붉은 청어입니다. 버그의 위치를 ​​지적한 점에서만 관련이 있습니다.

here-document의 구분 기호가 인용되어 있으므로 행이 확장되지 않습니다. 이 경우, 쉘은 입력에서 인용 된 것처럼 행을 읽습니다. 백 슬래시가 인용 된 컨텍스트에 표시되면 이스케이프 문자로 작동하지 않으며 (아래 참조) 백 슬래시-줄 바꾸기를 특수하게 처리하지 않습니다. 실제로 구분 기호의 일부를 인용하면 여기에 문서 행이 작은 따옴표처럼 읽 힙니다.

Posix 2.2.1의 텍스트는 어색하게 작성되었지만 백 슬래시는 인용되지 않은 경우에만 특별히 처리됨을 의미합니다. 백 슬래시를 인용하고 작은 따옴표 또는 다른 백 슬래시로만 모든 확장을 금지 할 수 있습니다.

마지막 부분은 작은 따옴표를 의미하는 "확장되지 않은"텍스트입니다. 이 표준은 2.2에서 문서는 "또 다른 형태의 인용"이라고 말하지만, 단어가 전혀 확장되지 않는 유일한 인용 형태는 작은 따옴표입니다. 따라서 작은 따옴표가 아닌 작은 따옴표와 거의 같은 인용 형식입니다.


@Scott (1) 나는 이것이 모든 질문에 대답하고 아무것도 불필요하다고 생각합니다. 답변을 시작하는 내 의견은 상황을 잘못 이해 한 중재자가 삭제 한 내용에 관한 것입니다. (2) 평판이 충분하지 않습니다. (3) 나는 대답을 삭제하는 사람들에 의해 비슷한 행동을 평가했을 것이지만, 앞으로도 그 점을 명심할 것입니다. 생각해 주셔서 감사합니다.
케빈

내 요점은 첫 번째 단락의 대부분이 Michael Mrozek과의 대화이며 질문에 대한 답변이 아니라는 것입니다. 게시물에 대해 언급 할만한 명성이 충분하지 않다는 것을 알고 있지만 메타 및 채팅에 충분하다고 생각합니다.
Scott

1
@ Scott 나는 당신이 대답을 간소화하려고 노력하고 있음을 이해하고 감사하지만, 이전에 정확하게 간소화 된 답변 (견적과 그에 대한 링크 만)을 게시했으며 중재자가 토론하지 않고 삭제했습니다. 삭제 된 게시물에 채팅에 대한 링크가없고 해당 결정에 이의를 제기 할 수 없습니다. 나는 그의 근거없는 비판에 답함으로써, 그것은 삭제에서 살아남을 수 있고, asker에 의해 받아 들여지고, 그 대답을 수정하여 서문을 제거하길 바랐다.
케빈
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.