web-dev-qa-db-ja.com

bash / zshスクリプトの "case"ステートメントの奇妙な構文の理由は何ですか?

プログラマーの観点から見ると、シェルスクリプトは、別のプログラミング言語であり、言語の規則を学び、それに準拠する必要があります。ただし、この構文は、かなり一般的に使用されている言語で今まで見た中で最も奇妙なスタイルであることを認めざるを得ません。シェルはこの構文を、それが派生した古い言語から採用しましたか?構文に特別な意味/意味はありますか?

例として、SOの another post から取った小さなスニペットを次に示します

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

これを見ると、最初にcaseesacで終わっていることがわかります。これはその逆の形式です(iffiで終わるような)。次に、各ケースの後に)が続くことを理解しています。十分に公正ですが、なぜ各ステートメントの終わりに2つの;が必要なのですか? )が付いていない(は醜いとも言えます。

言語の歴史的側面に関する詳細情報を探していますが、技術的な理由からもオープンです。

47
phunehehe

リクエストごと:

  • では、ループが「for ...; do ...; done」ではなく「for ...; do ...; od」である理由を推測できますか?それには正当な理由がありましたが、終わりを示すためにALGOLのような逆のキーワードが他の場所で使用されました。

回答:

  • 構文はBourne(Bourne Shellの名声)から来ています。彼はALGOLに取り組んでおり、ALGOLのシェル構文の一部をモデル化するのに十分に気に入っていました。 ALGOLは逆のキーワードを使用して構成の終わりをマークするため、「case ... esac」が適切でした。ループが「od」で終わらない理由は、Unixのコマンド「od」(8進ダンプ)がすでにあったためです。したがって、代わりに「完了」が使用されます。

評判では、Bourne Shellのソースコードは、ALGOLのように見えるようにマクロを使用して、特異なCで記述されています。このため、メンテナンスが困難でした。

主な質問について-なぜcaseステートメントの選択肢の前後に開き括弧(括弧)がないのかについて-いくつかの関連する理論があります。

まず、Bourne Shellが作成されたとき(1970年代後半)、 'ed'、 標準テキストエディター を使用して多くの編集が行われました。バランスのとれた括弧や他のそのような表記にスキップするという概念がないため、先行括弧は必要ありませんでした。また、ドキュメントを作成している場合は、引数を次のように整理することもできます。

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

多くの場合、左括弧は省略されます-caseステートメントはそのモデルに非常にうまく適合します。

もちろん、それ以来、閉じ括弧を入力するときに一致する開き括弧をマークするエディターに慣れてきたため、古いBourne Shell表記は厄介です。 POSIX標準では、先頭の括弧はオプションです。 POSIXライクなシェル(Korn、Bash、Zsh)の最新の実装はこれをサポートします。通常、/ bin/shが依然として忠実なBourneであるSolaris 10のようなマシンへの移植性について心配する必要がないときに使用します。先頭の括弧を許可しないシェル。 (私は通常、#!/bin/kshをシバンとして使用して対処します。)

37

;;を使用する理由は、次のように、単一の;を使用して複数のステートメントを1行で記述できるためです。

restart)
   stop; start;;
...
24
khachik

Bashは対応する括弧を受け入れることができます:

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

    etc.
11

右括弧は、自然言語のリストで次のように使用されることがあります。

1) do this
2) do that

逆転したキーワードは、ALGOLの一部の形式から取得されましたが、実際にはインタラクティブな使用には非常に良いアイデアです。それらは、if/elseを含む構成の終わりを明確に区別します。

たとえば、Cのような構文では、これが解析された後:

if (condition)
    command here;

elseが来るかどうかは?よりCに似た構文を持つPlan 9のシェルであるrcは、if notの代わりにelseを使用しますが、きれいではありません。

Bourne Shell構文では、elseまたはfiがあり、追加の入力を読み取る必要はありません。

3
jilles