sh 루프에서“do”다음에“;”이없는 이유는 무엇입니까?


28

셸 루프에서 한 줄에 쓸 때 ;문자 가없는 이유는 무엇 do입니까?

여기 내가 의미하는 바가 있습니다. 여러 줄에 쓰면 for루프는 다음과 같습니다.

$ for i in $(jot 2)
> do
>     echo $i
> done

그리고 한 줄에 :

$ for i in $(jot 2); do echo $i; done

접힌 모든 줄 은 줄을 제외하고; 그 다음에 나오며을do 포함 ;하면 오류입니다. 아마도 나보다 훨씬 똑똑한 사람이 이것이 이유가 옳은 일이라고 결정했지만 그 이유가 무엇인지 알 수는 없습니다. 나에게 일치하지 않는 것 같습니다.

와 같은 while너무 루프.

$ while something
> do
>     anotherthing
> done
$ while something; do anotherthing; done


2
일관성이 있습니다 : while/ 뒤에 세미콜론이 없습니다 for.
Dmitry Grigoryev

즉시 생각 나는 것은 그것이 필요하지 않다는 것입니다. 다른 곳에서 세미콜론은 문장을 구별합니다.
폴 드레이퍼

중복되기 때문입니다. 그것 없이는 모호성이 없습니다.
user207421

답변:


29

이것이 명령 구문입니다. 복합 명령 참조

for name [ [in [words …] ] ; ] do commands; done

구체적으로 참고하십시오 : do commands

대부분의 사람들이 넣어 docommands별도의 줄에 쉽게 읽을 수 있도록하지만, 필요하지 않습니다, 당신은 쓸 수 있습니다 :

for i in thing
do something
done

나는이 질문이 특별히 쉘에 관한 것이고 bash 매뉴얼에 링크되어 있음을 알고 있습니다. 쉘 매뉴얼에는 그렇게 쓰여 있지 않지만 Stephen Bourne 이 바이트 매거진을 위해 쓴 기사 에는 그렇게 쓰여 있습니다.

스티븐의 말 :

명령리스트 개행 또는 종료에 의해 분리 또는 하나 이상의 간단한 일련의 명령이다 ;(세미콜론). 또한, 같은 단어 예약 할 일을 하고 수행 일반적으로 줄 바꿈 앞에되거나 ;더 ...이 다음 명령 목록 때마다 설정 할 일이 실행됩니다.


5
같은 세미콜론 이 없어야하는 이유도 흥미로울 것 for i in thing; do; something; done입니다. 줄 바꿈이 허용되면 세미콜론은 허용되지 않습니다.
rexkogitans

@ gidds : 그렇습니다. 이것이 쉘 문법도 구성하는 방법입니다. 는 something주제이며 do그것을 적용됩니다. 영어 문장 구조 에서처럼.
Peter Cordes

@gidds 여러 명령이 ( while구문에서) 조건에 들어갈 수 있으므로 리터럴 (또는 다른 구문)이 필요하므로 조건 명령을 루프 본문 명령과 구별 할 수있는 것이 필요합니다. do그것들을 분리하기 위해 사용 하는 것이 아마도 가장 적합한 것처럼 보일 것입니다.
JoL

@rexkogitans 사실, 나는 그것이 구문 오류라는 것을 결코 깨닫지 못했다. 이 제목 질문도 매우 적합합니다. 아마도 빈 몸을 허용하지 않는 것과 관련이있을 것입니다. 그러나 줄 바꿈으로 빈 본문을 만들 때 약간 다른 구문 오류가 발생하며 예제에 빈 본문이 없습니다.
JoL

@rexkogitans 여기서 세미콜론은 루프 구문의 일부이며 명령 목록 종결 자로서의 다른 역할과 다릅니다. 줄 바꿈은 다르게 요구되거나 예상되지 않는 경우 일반 공백처럼 취급되기 때문에 다릅니다. 셸 문법이 지저분합니다.
chepner

12

이 구문의 원래 이유가 무엇인지 모르지만 while루프가 조건 섹션에서 여러 명령을 취할 수 있다는 사실을 고려하십시오.

while a=$(somecmd);
      [ -n "$a" ];
do
    echo "$a"
done

여기서 do키워드는 루프의 조건 섹션과 본문을 구분하는 데 필요합니다. dowhile, ifthen(및 done) 과 같은 키워드 이며 , 세미콜론이나 줄 바꿈이 필요하지 않지만 명령 바로 앞에 나타납니다.

(일반화 대안 ifwhile) 다소 추한 보일 것이다, 우리는 예를 작성해야 것

if; [ -n "$a" ]; then
    some command here
fi

for루프 구문은 비슷합니다.


11

셸 구문은 접두사를 기반으로합니다. 특수 키워드로 소개 된 절이 있습니다. 특정 조항이 함께 진행되어야합니다.

while루프는 하나 만들어 이상의 명령을 테스트하고있다 :

test ; test ; test ; ...

하나 이상의 body 명령으로

body ; body ; body ; ...

쉘에 while 루프가 시작된다는 것을 알려 주어야합니다. 이것이 while단어 의 목적입니다 .

while test ; test ; test ; ...

그러나 상황이 모호합니다. 몸의 시작은 어느 명령입니까? 무언가를 나타내야하며 do접두사가하는 일입니다.

do body ; body ; body ; ...

그리고 마지막으로, 마지막 몸이 보여 졌음을 나타내는 무언가가 있습니다. 특별한 키워드 done가 그렇게합니다.

이 쉘 키워드는 같은 행에서도 세미콜론 분리가 필요하지 않습니다. 예를 들어 여러 개의 중첩 루프를 닫으면을 가질 수 있습니다 done done done ....

세미콜론은 ... test ; body ... 같은 줄에 있으면 그 사이 에 있습니다. 이 세미콜론은 종결 자로 이해됩니다 test. 따라서 do키워드가 키워드 사이에 삽입되면 세미콜론과 사이에 있어야합니다 body. 세미콜론의 다른쪽에 있으면 test명령 사이에 배치되지 않고 명령 구문 내에 잘못 포함됩니다 .

쉘 구문은 원래 Stephen Bourne이 설계했으며 Algol에서 영감을 얻었습니다 . Bourne은 Algol을 너무 좋아하여 쉘 소스 코드에 C 매크로를 많이 사용하여 C를 Algol처럼 보이게했습니다. 버전 7 Unix에서 1979 날짜의 쉘 소스를 찾아 볼 수 있습니다 . 매크로는에 mac.h있으며 모든 곳에서 사용됩니다. 예를 들어, if문장은 IF... ELSE... ELIF... 로 렌더링됩니다 FI.


소스 코드가 인상적입니다.
keithpjolley

그래, 그것은 cpp의 여행 힘이다.
도난

7

나는 이것이 do특별히 특별하지 않다고 주장합니다 . ;명령 목록을 시작할 수 없기 때문에 오류가 발생 합니다. 만약 그렇다면, 첫 번째 명령은 비어 있고, 문법은 빈 명령을 허용하지 않습니다 (명령없이 변수 할당 또는 재 지정, 예, 그러나 아무것도 아님). 명령 목록이 필요한 곳이면 어느 곳에서나 가능합니다.

$ while true; do ; echo foo; done
dash: 1: Syntax error: ";" unexpected
$ while ; true; do; echo; done
dash: 1: Syntax error: ";" unexpected
$ { ; echo foo; }
dash: 1: Syntax error: ";" unexpected
$ if ; true; then echo foo; fi
dash: 1: Syntax error: ";" unexpected

조차:

$ ; ;
dash: 1: Syntax error: ";" unexpected

이 모든 곳에서 명령 목록이 필요하므로 행간 ;이 예상치 않습니다.


예- 'do'다음에 '\ n'을 임의로 추가 한 방식으로 'do'는 독립형 토큰이며 다음 블록에서 작동하는 것이 아니라고 생각했습니다.
keithpjolley

그것은 비 이스케이프 줄 바꿈 (그렇지 않은 것처럼 보인다 쉘 구문에서 세미콜론처럼 행동하는) 것을 어떻게 되는 후 허용 do(그리고 if비록, 등)?
Henning Makholm

@Henning 명령 목록 앞뒤에 여러 줄 바꿈이 허용됩니다. 개행과 세미콜론은 다른 측면에서도 다르게 작동합니다. 예를 들어, 명령 별이 아닌 전체 입력 행을 읽을 때 (즉, 다음 줄 바꿈까지) 별명 확장이 수행됩니다.
muru

3

구문은 다음과 같습니다.

for i in [whitespace separated list of values]
do [newline separated list of commands]
done

명령 목록 또는 "do"또는 "done"앞의 줄 바꿈은 ";"으로 바꿀 수 있습니다.

"do"다음과 "in"앞에 개행 ( ";"이 아님)을 사용할 수 있습니다 . 단지보기 좋게 만들기 위해 개행 을 요구 하는 것은 합리적이지 않습니다 .


3

if 키워드와 비슷합니다. 명령이 짧을 때 읽을 수 있습니다.

if   test_commands
then true_commands
else false_commands
fi

나는 임의에 넣고 있었어요 실현되면 \n이후에 do(당신이 생각하지 않는 긴만큼 모든 만든 의미 없는 임의에 넣을 수있는 \n다른 명령과 인수 사이).
keithpjolley

음, do, then, else하지 않는 인수 -가 있다면, 당신은 그들 앞에 세미콜론을 사용하도록 허용하지 않을 것입니다. 그들은 있습니다 쉘 키워드 (참조 type if then elif else fi)
글렌 잭맨

답장을 받고 싶어하는 것만 큼 명확하지 않은 것 같습니다.
keithpjolley

내 요점은 "do"는 "other command"와는 다르다는 것입니다. 따라서 다른 규칙을 따릅니다.
glenn jackman

3

이것은 POSIX shell grammar에 의해 지정되기 때문에 짧은 답변 입니다. do및 사이 done에있는 ;것은 명령문 그룹으로 간주 되며 순차적 구분 기호입니다.

for_clause       : For name                                      do_group
                 | For name                       sequential_sep do_group
                 | For name linebreak in          sequential_sep do_group
                 | For name linebreak in wordlist sequential_sep do_group

do_group         : Do compound_list Done 

sequential_sep   : ';' linebreak
                 | newline_list

또한 ;필요한 경우 표준에 명시 적으로 명시되어 있고 sequential_sepafter 가 포함됩니다 Do.


1
@drewbenn 당신은 첫 번째 것을 의미합니까? 그것은 위치 매개 변수를 반복합니다. 따라서 ./myscript.sh abc와 같은 스크립트가있는 경우 abc가 인수이면 i의 루프입니다. echo "$ i"; 비록 그것이 작동하기 위해서는 세미콜론이 필요하다고 생각하지만, abc를 반복 할 것입니다
Sergiy Kolodyazhnyy

좋아, 그래서 나의 의심도 사라졌다
Sergiy Kolodyazhnyy

1

do는 키워드이므로 그 뒤에 나오는 것은 본질적으로 매개 변수입니다. 배쉬 인터프리터는 더 많은 것을 알고 있습니다. ';'이없는 방법과 비슷합니다. for 명령에서 i를 따릅니다. 실제로 i 입력 후 개행을 추가하고 나머지를 새 줄에 입력하면 정상적으로 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.