POSIX 쉘 주석 및 줄 연속

POSIX 쉘 주석 및 줄 연속

내 질문을 명확히하기 위해 편집하십시오.

POSIX는 다음과 같이 말합니다.

<newline>이 <backslash> 뒤에 오는 경우(따옴표 제외), 쉘은 이를 줄 연속으로 해석합니다. 입력을 토큰으로 분할하기 전에 <backslash> 및 <newline>을 제거해야 합니다.

그러나 dash다른 구현에서는 입력에 먼저 레이블이 지정됩니다. 결과적으로 \<newline>인식되지 않고 # this is a comment \폐기됩니다. 이 동작은 POSIX를 준수합니까? POSIX는 다시 말합니다토큰화 전에 연속된 줄을 제거해야 합니다..

다음 절차는 실제로 POSIX와 호환되지 않습니까?

  1. 전체 입력을 읽으십시오."echo hello ... \<newline> ... bye"
  2. 인용되지 않은 콘텐츠를 검색하여 \<newline>삭제하세요."echo hello ... bye"
  3. 토큰화:"echo"(discard ' ')"hello"(discard ' ')(discard "# ... bye")

Ubuntu에서 dash-0.5.10.2-6 sh(대시)를 사용하면 다음을 얻을 수 있습니다.

$ cat /var/tmp/test.sh
echo hello # this is a comment \
echo bye

$ sh /var/tmp/test.sh
hello
bye

# 이후의 모든 내용은 주석으로 처리되고 \ 이전의 모든 내용은 삭제되므로 \<newline>의 줄 연속은 효과가 없기 때문입니다.

하지만,POSIX "이스케이프 문자(백슬래시)" 섹션상태

입력을 토큰으로 분할하기 전에 <backslash> 및 <newline>을 제거해야 합니다.

~부터# 주석 처리는 토큰화로 수행됩니다.,

echo hello # this is a comment \
echo bye

다음과 같아야 합니다.

echo hello # this is a comment echo bye

이것은 sh가 POSIX와 호환되지 않는다는 것을 의미합니까? 아니면 이 경우 주석이 줄 연속보다 우선시되는 이유가 있습니까?

답변1

섹션 1에 설명된 대로 쉘에 대한 입력은 문자별로 스캔되어 토큰으로 나뉩니다.토큰 인식.

[...] 쉘은 아래의 첫 번째 적용 가능한 규칙을 적용하여 입력을 토큰으로 나눕니다.다음 문자로입력에.

따옴표는 토큰 인식 프로세스의 일부로 처리되지만 질문의 예를 고려하면 셸은 #그 앞에 따옴표로 묶인 개행 문자를 만나게 됩니다.

쉘이 입력 행을 스캔하는 동안 따옴표가 없는 주석 문자에 도달하면 행의 나머지 부분(마지막 백슬래시 포함)이 주석으로 삭제됩니다.

현재 문자가 이면 #해당 문자와 ​​모든 후속 문자(다음 문자 제외)가 <newline>주석으로 삭제됩니다. 줄 의 끝은 <newline>주석의 일부로 간주되지 않습니다.


당신이 인용한 표준 섹션은인용하다섹션에서는 백슬래시 앞에 개행 문자가 나타날 때...

따옴표가 없는 A는 <backslash>a를 제외한 후속 문자의 리터럴 값을 유지해야 합니다 <newline>. 가 <newline>뒤에 오면 <backslash>쉘은 이를 줄 연속으로 해석합니다. 입력을 토큰으로 <backslash>분할하기 전에 제거해야 합니다. <newline>[...]

이는 스캐너가 실제로 따옴표가 없는 백슬래시를 발견할 때까지 적용되지 않습니다(토큰 인식 프로세스에서 처리됨).

현재 문자가 <backslash>작은따옴표 또는 큰따옴표이고 인용되지 않은 경우 인용된 텍스트가 끝날 때까지 후속 문자의 인용에 영향을 줍니다. 인용 규칙은 "인용"에 설명된 대로입니다.

이 답변에서 이미 언급했듯이 스캐너는 주석 문자를 먼저 만난 다음 백슬래시를 만나게 되며, 이는 줄의 나머지 부분(인용 문자 포함)을 comment 로 처리하는 토큰 인식 규칙을 트리거합니다. 따라서 줄 끝 개행에 대한 참조는 결코 적용되지 않습니다.

답변2

흥미로운 아이디어입니다. 백슬래시 이스케이프는 토큰이 인식되기 전에 전체 입력에 적용되는 단계라고 생각하는 것 같지만 그렇지 않습니다.

입력은 여전히 ​​왼쪽에서 오른쪽으로 엄격하게 평가되며, 이는 인용과 같은 다른 경우에 필요합니다.

echo 'foo\
bar'

또 다른 상황은 상황적 이유로 인해 참조된 규칙이 적용되지 않는 경우입니다. 이 경우 컨텍스트는 귀하의 경우 주석을 기반으로 하는 인용 문자열입니다.

현재 문자가 "#"인 경우 해당 문자와 ​​이후의 모든 문자(다음 문자 제외)는 주석으로 삭제됩니다.

문장을 인용하는 이유는 다음과 같이 할 수 있기 때문입니다.

ec\
ho foo

따라서 왼쪽에서 오른쪽으로 표시하여 표시합니다. 여전히 일반적인 상황에서 토큰 분할 전에 백슬래시 + 개행 문자를 제거하면 평가가 간단해집니다 echo.

dash이 동작은 POSIX 셸에만 적용되는 것이 아닙니다 .

답변3

답변해 주셔서 감사합니다.

\토큰화 시 참조되었는지 알고 있으므로 \<newline>토큰화 전에 참조되지 않은 콘텐츠를 제거할 수 없습니다.

입력을 토큰으로 분할하기 전에 <backslash> 및 <newline>을 제거해야 합니다.

이 진술은 단순히 다른 참조와 달리 \<newline>즉시 폐기된다는 것을 말합니다. 나는 그렇게 생각해야 한다.

관련 정보