bash/zsh 스크립트에서 "case"문의 이상한 구문이 나타나는 이유는 무엇입니까?


37

프로그래머의 관점에서 볼 때 쉘 스크립트는 언어의 규칙을 배우고 준수해야하는 또 다른 프로그래밍 언어 일뿐입니다. 그러나이 구문은 내가 흔히 사용하는 언어에서 본 이상한 스타일이라는 것을 인정해야합니다. 쉘은이 구문을 이전 언어에서 가져 왔습니까? 문법에 특별한 의미/의미가 있습니까? 예를 들어

가, 여기에 내가이 보면 SO

case "$1" in 
    start) 
     start 
     ;; 
    stop) 
     stop 
     ;; 
    restart) 
     stop 
     start 
     ;; 
    status) 
     check_status 
     ;; 
    *) 
     echo "Usage: $0 {start|stop|restart|status}" 
     exit 1 
     ;; 
esac 

another post 걸릴 작은 조각이다, 첫째로 나는 case 결말처럼 (그 반대 형태 인 esac로 끝나는 if 것을 볼 수 있습니다 in fi). 둘째, 나는 각 사례 뒤에 )이 오는 것을 이해합니다. 공정한,하지만 왜 지구상에서 각 진술의 끝에 ;이 필요합니까? 나는 또한 ( 동반하지 않고 ) 못생긴다고 말할 것입니다.

언어의 역사적 측면에 대해 더 자세히 알고 싶습니다. 기술적 인 이유로도 열려 있습니다.

+2

그래서 왜 루프가 'for ...인지 ...? ...; 완료 '가 아니라'...; ...; od '? 그럴만한 이유가 있었지만, 끝을 표시하는 Algol과 같은 역전 된 키워드는 다른 곳에서 사용되었습니다. 21 nov. 102010-11-21 17:43:53

  0

@Jonathan 나는 왜 이런 식으로 그렇게하지 않는지 논쟁하지 않고있다. (나는 이것을 처음부터 분명하게 만들었다 고 생각한다). 제 질문은 "추악한 구문은 어디에서 왔습니까?" 22 nov. 102010-11-22 12:14:32

+4

구문은 Bourne (Bourne shell 명성의)에서 유래되었습니다. 그는 Algol을 연구했고, Algol의 쉘 구문을 모델링하기에 충분했습니다. Algol은 구문의 끝을 표시하기 위해 역순으로 키워드를 사용하므로 'case ... esac'가 적절합니다. 루프가 'od'로 끝나지 않는 이유는 Unix - octal dump에 이미 'od'명령이 있다는 것입니다. 따라서 '완료'가 대신 사용됩니다. (그리고 평판에 의해, Bourne 쉘 소스 코드는 특이한 C 언어로 작성되어 Algol처럼 보이게 만들었 기 때문에 유지하기가 어려웠습니다.) 22 nov. 102010-11-22 12:29:57

  0

@Jonathan 좋은 답변입니다. :) 22 nov. 102010-11-22 16:10:08

27

:

  • 그래서 당신이 추측 할 수는 루프 'for ...; do ...; done'이고하지 'for ...; do ...; od'왜? 그럴만한 이유가 있었지만, 끝을 표시하는 Algol과 같은 역전 된 키워드는 다른 곳에서 사용되었습니다.

답변 :

  • 구문은 (명성 쉘 Bourne 씨의) Bourne의에서왔다. 그는 Algol을 연구했고, Algol의 쉘 구문을 모델링하기에 충분했습니다. Algol은 역행 된 키워드를 사용하여 구문의 끝을 표시하므로 '사례 ...esac '이 적절했다. 루프가 'od'로 끝나지 않는 이유는 Unix - octal dump에 이미 'od'명령이 있다는 것입니다. 따라서 '완료'가 대신 사용됩니다.

Bourne 쉘 소스 코드는 idiosyncratic C로 매크로로 작성되어 Algol처럼 보입니다. 이로 인해 유지 관리가 어려워졌습니다.

중요한 질문과 관련하여 - 왜 case 진술에 대안을 둘러싼 대괄호 (괄호)를 사용하지 않는지에 대해 - 나는 몇 가지 관련 이론을 가지고 있습니다.

우선 Bourne 쉘이 작성되었을 때 (1970 년대 후반), 많은 편집이 'ed', standard text editor으로 이루어졌습니다. 균형 괄호 또는 다른 표기법으로 건너 뛰는 개념이 없으므로 선행 괄호를 사용할 필요가 없습니다. 문서를 작성하는 경우 또한, 당신은 잘 당신의 인수를 마샬링 수 있습니다 여는 괄호는 종종 생략

a) ...blah... 
b) ...more... 
c) ...again... 

- 그리고 case 문은 아주 행복하게 그 모델에 맞는 것입니다.

물론, 그 이후로 우리는 닫는 괄호를 입력 할 때 일치하는 여는 괄호를 표시하는 편집기에 익숙해 져 있으므로 이전의 Bourne 셸 표기법은 불편합니다. POSIX 표준은 선행 괄호를 선택적으로 만듭니다. POSIX 같은 쉘 (Korn, Bash, Zsh)의 가장 현대적인 구현은이를 지원할 것이고 일반적으로/bin/sh가 여전히 충실한 Solaris 10과 같은 기계에 대한 이식성에 대해 걱정할 필요가 없을 때 사용합니다. 쉘은 선행 괄호를 허용하지 않습니다. (나는 보통 #!/bin/ksh을 사용한다.)

+1

"주요 질문"은 Algol이라는 구문의 원점이라고 말할 수 있습니다 (bash의 Wikipedia 페이지에서 찾을 수 없음). 좋은 답변 어쨌든 :) 23 nov. 102010-11-23 03:41:07

+1

'원래'본 셸에 대한 정보는 소스 보지 (그리고 다른 장소에서 찾을 수있는 [Heirloom Bourne Shell] (http://heirloom.sourceforge.net/sh.html) 프로젝트에서 찾을 수 있습니다. 검색 엔진). 23 aug. 132013-08-23 22:44:46


16

;;를 사용하는 이유는 하나의 ; 같이, 하나 개의 라인에 여러 개의 문을 작성하는 데 사용될 수있다 :

restart) 
    stop; start;; 
... 

9

배시 일치 호 수락 할 수

case "$1" in 
    (start) 
     start 
     ;; 
    (stop) 
     stop 
     ;; 

    etc. 
+1

POSIX and Korn 쉘은 선행 괄호도 허용합니다. 옛날 옛적에 'ed'('표준 텍스트 편집기'- UNIX 운영체제의 제 7 판에서는 '열린 괄호와 일치하는 바운스 커서'옵션이 없었기 때문에 열린 괄호는 실제로는 아니 었습니다 필요한. 21 nov. 102010-11-21 17:52:49

  0

Autoconf와 친구들은'in (''case "$ 1"# ((')) 뒤에 적절한 괄호를 사용하여 주석을 달기를 선호합니다. 편집자는 새로운 구문과 비슷하지만 원래의 Bourne 셸에서도 작동합니다. 21 nov. 102010-11-21 22:18:47

  0

@Dennis는 알아두면 좋겠지 만 일치하지 않는 스타일이 인기를 얻은 전후입니까? 22 nov. 102010-11-22 12:24:48

  0

@phunehehe : 무슨 뜻인지 모르겠네요. "case"/ "esac"가 열린 괄호를 허용하지 않는 셸이 있는지 여부를 알고 싶지 않다면, 그 답은 "예"입니다. 원래의 Bourne 셸이 하나의 예입니다 22 nov. 102010-11-22 12:33:27

  0

아니, bash는 처음부터 일치하는 괄호를 수락 했습니까? 나중에 누군가가 추함에 대해 불평 할 때 기능으로 올 수 있습니까? 22 nov. 102010-11-22 16:12:21

  0

@phunehehe :이 문서는 2.0 (1996)에서 2.05b (20) 사이에 언젠가 바뀌 었습니다. 02). 그것이 문서화되기 전에 그것이 받아 들여 졌는지 나는 모른다. [변경 사항] (http://tiswww.case.edu/php/chet/bash/CHANGES)이이 주제에 대해 침묵하는 것으로 보입니다. 22 nov. 102010-11-22 17:54:19


3

닫는 괄호 때로는 자연어 목록에 사용됩니다.

1) do this 
2) do that 

역전 된 키워드는 어떤 형태의 Algol에서 가져 왔지만 대화 형으로 사용하기에 좋은 아이디어입니다. 그들은 if/else를 포함하여 구조의 끝을 명확하게 구분합니다. 이 후 C 형 구문 예

는 파싱되었습니다

if (condition) 
    command here; 

가있는 else오고 아닌지? rc, 더 C와 유사한 구문을 가진 Plan 9의 셸은 else 대신 if not을 제공함으로써이를 해결하지만 꽤 맞지 않습니다.

Bourne 쉘 구문을 사용하면 else 또는 fi이되며 추가 입력을 읽을 필요가 없습니다. 요청에 따라

  0

목록에 대한 귀하의 요지를 볼 수 있지만 else 부분은별로 의미가 없습니다. 어느 쪽이든 추가 입력은 'else'또는 'fi'인지 확인하기 위해 읽어야합니다. 22 nov. 102010-11-22 12:22:23

  0

그러나 추가 입력은'if'의 일부입니다. 'else'가있는 C와 유사한 구문으로, else가 없으면 쉘은 다음 명령을 읽습니다. 이는 대화 형 쉘에서 다소 예상치 못한 결과입니다. 22 nov. 102010-11-22 22:30:04