POSIX Shell Grammar에서 여는 중괄호 뒤에 중괄호 명령 그룹에 공백이 필요한 이유는 무엇입니까? reserved words are recognized. */ %token Lbrace

TL; DR : POSIX 괄호 그룹에 {예약어 뒤에 공백이 필요 하지만 서브 쉘에 예약어 뒤에 공백이 필요한 이유는 무엇 (입니까?

POSIX 쉘 문법은 다음과 같이 중괄호 그룹과 서브 쉘을 정의합니다.

brace_group      : Lbrace compound_list Rbrace

subshell         : '(' compound_list ')'

이제 문자 그대로 읽으면 공백이 중요합니다. 이것은 다음과 같이 여는 중괄호와 괄호를 나타내는 공간이 있어야 함을 의미합니다.

{ echo hello world; }

( echo hello world )

이것은 복합 명령 정의 와도 일치 합니다 .

이러한 복합 명령 각각에는 시작 부분에 예약어 또는 제어 연산자가 있고 끝에 해당 터미네이터 예약어 또는 연산자가 있습니다.

그러나하지 않습니다 어떤 의미가 이유 (list)( list )잘 (공간 후에는 그 일 (즉, 그러나 중괄호 확장은 선도적 인 공간을 가지고 있어야 필요하지 않습니다) {echo hello;}작동하지 않을 것입니다.

물론 셸 단어로 취급되는 예약어는 필드 분할 개념과 정렬하기 위해 공백이 필요하다는 것은 당연 하지만 정의 자체는 공백을 언급하지 않습니다. 또한 복합 명령의 POSIX 정의에 의해 예약어로 간주되고 예약어 인 경우 {, (예약어 뒤에 공백 문자와 관련하여 다르게 취급되는 이유는 무엇입니까? 이제 ksh (1) 매뉴얼의 상태는 다음과 같습니다.

일련의 문자 인 단어는 따옴표없는 공백 문자 (공백, 탭 및 줄 바꿈) 또는 메타 문자 (<,>, |,;, &, (및))로 구분됩니다.

다시 말해, ksh는 (단어 구분 기호로 인식 되며, 첫 번째 단어는 명령 또는 변수 할당입니다. 그러나 POSIX (는 메타 문자 로 언급되지 않습니다 . POSIX 문법에 관한 한 가능한 설명 {은 “토큰”으로 간주되는데, 여기에 (나열되지 않습니다.

/* These are reserved words, not operator tokens, and are
   recognized when reserved words are recognized. */


%token  Lbrace    Rbrace    Bang
/*      '{'       '}'       '!'   */

이 불일치에 대한 정확한 추론은 무엇입니까?

허용되는 답변 메모 :

  • 에 허용 체크 이전 이삭의 대답 은 q를 제공하기 때문에 표준 형성 uote 직접 내 질문을 해결 자체를 :

    예를 들어, ‘(‘및 ‘)’는 제어 연산자이므로 <space>(list)에는 필요 하지 않습니다 . 그러나 ‘{‘및 ‘}’은 {list;}에서 예약어이므로이 경우 선행 <space><semicolon>필수입니다.

  • Kusalananda의 답변 수락 . Kusalananda의 답변은 대부분 비공식적이고 직관적 인 관점에서 필자에게 필요한 것을 설명합니다. 그것은 {예약어이며 지적 (입니다. Michael Homer는 또한 의견에서 복합 명령 정의 상태 (강조 추가)에 대해서도 동일하게 언급했습니다.

    이러한 각 복합 명령에는 처음에 예약어 또는 제어 연산자 가 있습니다.

  • {유사 예약 된 단어로 정의 for또는 while쉘 문법에 나열된, (질문의 마지막 코드 블록을 참조)

  • 섹션 2.9 상태 (강조 추가) :

    특히, 표현에는 토큰 이 필요하지 않은 (토큰 중 하나가 연산자 인 경우)에서 토큰 사이의 간격이 포함됩니다 .<blank>

  • 표준은 명시 적으로 (연산자로 정의되지 않지만 연산자 (라고합니다. 구체적으로, 섹션 2.9.2

    파이프 라인이 예약어! 그리고 command1은 서브 쉘 명령이며, 응용 프로그램은 (command1의 시작 부분에있는 연산자가 하나 이상의 문자로!와 분리되어 있는지 확인해야합니다.) 예약어!

  • Digital Trauma의 스택 오버플로관한 질문은 예약어에 관한 2.4 절을 지적합니다.

    이 인식은 문자를 인용하지 않고 단어를 다음과 같이 사용하는 경우에만 발생합니다.

    -명령의 첫 단어

  • Kusalananda의 답변에서 언급했듯이 “POSIX 문법에 표시된 공백은 쉘 입력 데이터에 있어야하는 공백이 아니라 문법 자체를 표시하는 방법 일뿐입니다. 중괄호는 예약어입니다. 마이클 호머 (Michael Homer )가 논평에서 언급 한대로 “공백이 중요하다면 공간을 생산 에 포함시켜야합니다. “

경우 폐쇄.



답변

그것은 쉘이 줄을 토큰으로 나누는 방식의 한계입니다.

쉘은 입력 파일에서 을 읽고 섹션 2 “쉘 소개”에 따라 행을 단어연산자 로 변환합니다 .

  1. 쉘은 입력을 토큰으로 나눕니다 : 단어와 연산자

{는 예약어입니다

일부 단어는 예약어입니다

예약어는 쉘에 특별한 의미가있는 단어입니다. 다음 단어는 예약어로 인식됩니다.

! { } case do done elif else esac fi for if in then until while

단어로 인식 되려면 단어를 구분 해야합니다 .

예약어는 구분 된 경우에만 인식됩니다 …

대부분 공백 (7 점) 과 연산자로 표시됩니다.

  1. 현재 문자가 인용되지 않은 <공백>이면, 이전 문자를 포함하는 토큰이 분리되고 현재 문자는 폐기됩니다.

(연산자입니다

운영자는 스스로 대기합니다 .

반면 연산자는 구분자입니다.

어디에서 “사업자”중 하나입니다 :

3.260 연산자

쉘 명령 언어에서 제어 연산자 또는 리디렉션 연산자

리디렉션 연산자는 다음 같습니다.

리디렉션 연산자

쉘 명령 언어에서 리디렉션 기능을 수행하는 토큰. 다음 기호 중 하나입니다.

<     >     >|     <<     >>     <&     >&     <<-     <>

제어 연산자는 다음 같습니다.

3.113 제어 연산자

쉘 명령 언어에서 제어 기능을 수행하는 토큰. 다음 기호 중 하나입니다.

&   &&   (   )   ;   ;;   newline   |   ||

결론

따라서 ‘(‘및 ‘)’는 제어 연산자이고 ‘{‘ ‘}’은 예약어입니다.

그리고 당신의 질문에 대한 정확한 설명은 사양 안에 있습니다 :

예를 들어, ‘(‘및 ‘)’는 제어 연산자이므로 (목록)에 <space>가 필요하지 않습니다. 그러나 ‘{‘및 ‘}’은 {list;}에서 예약어이므로이 경우 선행 <space> 및 <semicolon>이 필요합니다.

다음에 공백 (또는 다른 구분 기호)이 필요한 이유를 정확하게 설명합니다 {.

유효합니다 :

{ echo yes;}

이대로 :

{(echo yes);}

이:

{(echo yes)}

또는 이것조차도 :

{>/dev/tty echo yes;}

답변

중괄호 괄호 차이는 괄호 (그리고 그이다 !)처럼 예약어 for, if, then괄호 제어 연산자 동안 등. 단어는 공백으로 구분해야합니다.

이것은 당신이 할 수없는 것처럼

foriin*; do

당신은 가질 수 없습니다

{somecommand;} >file

또는

if !somecommand; then

POSIX 문법에 표시된 공백은 쉘 입력 데이터에 있어야 할 공백이 아니라 문법 자체를 표시하는 방법입니다. 괄호 소유하고 있다는 사실이다 단어를 서브 쉘의 괄호 안하면서 그들이 공백으로 둘러싸인 할 필요가 있음을 의미한다 그.