{는 예약어입니다

{는 예약어입니다

긴 이야기 짧게: POSIX 중괄호 그룹에서는 예약어 뒤에 공백이 필요 {하지만 하위 쉘에서는 예약어 뒤에 공백이 필요하지 않은 이유는 무엇입니까 (?

POSIX 쉘 구문은 중괄호 그룹과 하위 쉘을 다음과 같이 정의합니다.

brace_group      : Lbrace compound_list Rbrace

subshell         : '(' compound_list ')'

이제 이것을 문자 그대로 받아들이면 공간이 중요합니다. 이는 아래와 같이 괄호뿐만 아니라 여는 중괄호와 닫는 중괄호를 표시할 공간이 있어야 함을 의미합니다.

{ echo hello world; }

( echo hello world )

이는 또한 다음과 일치합니다.복합 명령 정의:

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

그러나 이해가 되지 않는 것은 이유이며 잘 작동하지만( (list)후행 공백이 필요하지 않음) 중괄호 확장에는 선행 공백이 있어야 합니다. 즉, 작동하지 않습니다.( list )({echo hello;}

물론 예약어를 쉘 단어로 취급하는 것이 합리적이며 개념과 일치하기 위해 뒤에 공백이 와야 합니다.필드 분할, 그러나 정의 자체에서는 공백에 대해 언급하지 않습니다. 또한 복합 명령의 POSIX 정의가 및 예약어를 {모두 처리하는 경우 이러한 예약어 뒤의 공백 문자와 관련하여 다르게 처리되는 이유는 무엇입니까? (지금,크쉬(1)설명서에는 다음과 같이 명시되어 있습니다.

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

즉, ksh가 (첫 번째 단어가 명령 또는 변수 할당인 단어 구분 기호로 인식하는 것이 합리적입니다. 그러나 POSIX에서는 메타문자를 언급하지 않는 것 같습니다 (. POSIX 구문 측면에서 내가 찾은 유일한 설명은 {"토큰"으로 처리되며 as는 (그 중 하나로 나열되지 않는다는 것입니다.

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


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

그렇다면 이러한 차이가 발생하는 정확한 이유는 무엇입니까?

수락된 답변 댓글:

  • 허용된 체크 표시를 다음으로 이동하세요.이삭의 대답q를 제공하기 때문에참고문헌 양식 표준그 자체로 내 문제를 직접 해결했습니다.

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

  • Kosalonanda의 답변을 수락하세요 . Kusarananda의 답변은 대부분 비공식적이고 직관적인 관점에서 볼 때 내 요구 사항을 충족했지만 {is는 예약어이고 (is 연산자임을 지적했습니다 . Michael Homer는 주석에서 동일한 상황을 지적했습니다. 복합 명령 정의 상태(강조 추가):

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

  • {Shell Grammar 와 유사 for하거나 나열된 예약어로 정의됩니다 while(질문의 마지막 코드 블록 참조).

  • 섹션 2.9에서는 다음과 같이 설명합니다(강조 추가).

    특히 이러한 표현에는 마커 사이의 간격이 포함됩니다.s가 필요하지 않은 일부 <blank>장소(토큰 중 하나가 운영자인 경우).

  • (연산자는 표준에 의해 명시적으로 정의되지 않지만 (단순히 연산자라고 합니다.섹션 2.9.2설명하다

    파이프가 예약어로 시작하는 경우! 그리고 command1은 서브셸 명령이므로 응용 프로그램은 command1 시작 부분의 ( 연산자가 !로 하나 이상의 문자로 구분되어 있는지 확인해야 합니다. ( 연산자 바로 다음에 오는 예약어 !의 동작은 지정되지 않습니다.

  • 스택 오버플로에 대한 질문Digital Trauma는 예약어에 대한 섹션 2.4를 지적합니다.

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

    -명령의 첫 번째 단어

  • Kusalananda의 답변에서 언급했듯이 "POSIX 구문에 표시된 공백은 쉘 입력 데이터에 있어야 하는 공백이 아니라 구문 자체를 표시하는 방법일 뿐입니다. 중괄호가 예약어라는 사실은 언급한 바와 같이 공백으로 둘러싸여 있습니다.마이클 호머댓글: "이러한 공간이 그 자체로 중요하다면 나열해야 합니다.생산"

경우 폐쇄.

답변1

중괄호와 괄호의 차이점은 중괄호(및 )는 , etc !와 같은 예약어 이고 괄호는 제어 연산자라는 것 입니다 . 단어는 공백으로 구분해야 합니다.forifthen

가질 수 없다는 뜻이다

foriin*; do

당신은 가질 수 없습니다

{somecommand;} >file

또는

if !somecommand; then

POSIX 구문에 표시된 공백은 쉘 입력 데이터에 있어야 하는 공백이 아니라 구문 자체를 표시하는 방법일 뿐입니다. 실제로 중괄호는 예약되어 있습니다.성격즉, 하위 쉘 괄호는 공백으로 묶어야 하지만 그렇지 않습니다.

답변2

이는 쉘이 행을 토큰으로 나누는 방식의 제한사항입니다.

껍질에 이렇게 써있어요철사입력 파일에서섹션 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;}

관련 정보