내 질문을 명확히하기 위해 편집하십시오.
POSIX는 다음과 같이 말합니다.
<newline>이 <backslash> 뒤에 오는 경우(따옴표 제외), 쉘은 이를 줄 연속으로 해석합니다. 입력을 토큰으로 분할하기 전에 <backslash> 및 <newline>을 제거해야 합니다.
그러나 dash
다른 구현에서는 입력에 먼저 레이블이 지정됩니다. 결과적으로 \<newline>
인식되지 않고 # this is a comment \
폐기됩니다. 이 동작은 POSIX를 준수합니까? POSIX는 다시 말합니다토큰화 전에 연속된 줄을 제거해야 합니다..
다음 절차는 실제로 POSIX와 호환되지 않습니까?
- 전체 입력을 읽으십시오.
"echo hello ... \<newline> ... bye"
- 인용되지 않은 콘텐츠를 검색하여
\<newline>
삭제하세요."echo hello ... bye"
- 토큰화:
"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>
즉시 폐기된다는 것을 말합니다. 나는 그렇게 생각해야 한다.