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 “쉘 소개”에 따라 행을 단어 나 연산자 로 변환합니다 .
- 쉘은 입력을 토큰으로 나눕니다 : 단어와 연산자
{는 예약어입니다
예약어는 쉘에 특별한 의미가있는 단어입니다. 다음 단어는 예약어로 인식됩니다.
! { } case do done elif else esac fi for if in then until while
예약어는 구분 된 경우에만 인식됩니다 …
대부분 공백 (7 점) 과 연산자로 표시됩니다.
- 현재 문자가 인용되지 않은 <공백>이면, 이전 문자를 포함하는 토큰이 분리되고 현재 문자는 폐기됩니다.
(연산자입니다
반면 연산자는 구분자입니다.
어디에서 “사업자”중 하나입니다 :
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 문법에 표시된 공백은 쉘 입력 데이터에 있어야 할 공백이 아니라 문법 자체를 표시하는 방법입니다. 괄호 소유하고 있다는 사실이다 단어를 서브 쉘의 괄호 안하면서 그들이 공백으로 둘러싸인 할 필요가 있음을 의미한다 그.