긴 이야기 짧게: 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 !
와 같은 예약어 이고 괄호는 제어 연산자라는 것 입니다 . 단어는 공백으로 구분해야 합니다.for
if
then
가질 수 없다는 뜻이다
foriin*; do
당신은 가질 수 없습니다
{somecommand;} >file
또는
if !somecommand; then
POSIX 구문에 표시된 공백은 쉘 입력 데이터에 있어야 하는 공백이 아니라 구문 자체를 표시하는 방법일 뿐입니다. 실제로 중괄호는 예약되어 있습니다.성격즉, 하위 쉘 괄호는 공백으로 묶어야 하지만 그렇지 않습니다.
답변2
이는 쉘이 행을 토큰으로 나누는 방식의 제한사항입니다.
껍질에 이렇게 써있어요철사입력 파일에서섹션 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;}