web-dev-qa-db-ja.com

なぜシェルでは0が真で1が偽ですか?

false; echo $?

上記は1を出力しますが、これは私が知っている他のすべてのプログラミング言語と矛盾しています。

これには何か理由がありますか?

102
httpinterpret

これは慣習ですが、考えてみると特に便利です。一般に、プログラムが成功した場合、それだけを知っておく必要があります。ただし、失敗した場合は、失敗に関するすべての種類の情報(発生理由、修正方法など)を知る必要があるかもしれません。 、必要に応じて詳細について特定のエラーを調査します。多くのAPIとフレームワークには同様の規則があります-成功した関数は0を返し、失敗した関数は特定の失敗のケースを説明するエラーコードを返します。

84
Carl Norum

Bashはプログラミング(スクリプト)言語ですが、シェルおよびユーザーインターフェイスでもあります。 0がエラーであった場合、プログラムは1種類のエラーしか表示できませんでした。

ただし、Bashでは、ゼロ以外の値はエラーであり、1〜255の任意の数値を使用してエラーを表すことができます。これは、さまざまな種類のエラーが発生する可能性があることを意味します。 1は一般的なエラー、126は、ファイルを実行できないことを意味し、127は「コマンドが見つかりません」などを意味します。最も一般的な終了コードのいくつかを示す、特別な意味を持つ終了コード の終了コードのリストは次のとおりです

多くの種類の成功もあります(終了ステータスは0)。ただし、成功すると次のステップに進むことができます。結果を画面に出力したり、コマンドを実行したりすることができます。

66

ここには2つの関連する問題があります。

まず、OPの質問、シェルで0が真で偽が1なのはなぜですか?、2番目、アプリケーションが成功と非成功に対して0を返す理由-失敗の場合はゼロですか?

OPの質問に答えるには、2番目の質問を理解する必要があります。この投稿に対する多数の回答は、これが慣習であると説明しており、この慣習が提供するいくつかの便利さをリストしています。これらの機能の一部を以下にまとめます。

アプリケーションが成功した場合に0を返し、失敗した場合にゼロ以外を返すのはなぜですか?

操作を呼び出すコードは、操作の終了ステータスについて2つのことを知る必要があります。 操作は正常に終了しましたか?[* 1]そして、操作が正常に終了しない場合、操作が正常に終了しなかったのはなぜですか?値は成功を示すために使用できます。ただし、0はプラットフォーム間で移植可能であるため、他の数値よりも便利です。これに対するxiboの回答の要約 question 2011年8月16日:

ゼロはエンコードに依存しません。

One(1)を32ビット整数のWordに保存したい場合、最初の質問は「ビッグエンディアンの単語かリトルエンディアンの単語か?」で、その後に「バイトがリトルエンディアンの単語を構成する長さは?」 「ゼロは常に同じように見えますが。

また、ある時点でerrnoをcharまたはshortにキャストするか、フロートすることさえ期待する必要があります。 (int)((char)ENOLCK)は、charが少なくとも8ビット長でない場合はENOLCKではありません(7ビットASCII charマシンはUNIXでサポートされています)、一方、(int)(( char)0)は、charのアーキテクチャの詳細に依存しない0です。

0が成功の戻り値になると判断されると、失敗の場合はゼロ以外の値を使用するのが理にかなっています。これにより、多くの 終了コード が操作が失敗した理由の質問に答えることができます。

なぜシェルでは0がtrueだがfalseが1なのか?

シェルの基本的な使用法の1つは、スクリプトを記述してプロセスを自動化することです。通常、これは操作を呼び出してから、操作の終了ステータスに基づいて条件付きで何か他のことを行うことを意味します。 Philippe A。 は、この投稿に対する彼の答えでうまく説明しました。

一般的にbashおよびUNIXシェルでは、戻り値はブール値ではありません。これらは整数の終了コードです。

これらの操作の終了ステータスをブール値として解釈する必要があります。成功した(0)終了ステータスをtrueに、ゼロ以外/失敗の終了ステータスをfalseに設定します。これにより、チェーンされたシェルコマンドの条件付き実行が可能になります。

次に例を示しますmkdir deleteme && cd $_ && pwd。シェルは0をtrueと解釈するため、このコマンドは期待どおりに機能します。シェルが0をfalseと解釈する場合、各操作の解釈済み終了ステータスを反転する必要があります。

要するに、アプリケーションが正常終了ステータスに対して0を返すという規則を考えると、シェルが0をfalseとして解釈することは無意味です。


[* 1]:はい、多くの場合、オペレーションは単なる成功メッセージ以上のものを返す必要がありますが、それはこのスレッドの範囲外です。

高度なBashスクリプトガイドの 付録E も参照してください。

24
axiopisty

私が理解することが重要だと思う基本的なポイントはこれです。一般的にbashおよびUNIXシェルでは、戻り値はブール値ではありません。これらは整数の終了コードです。そのため、0は成功を意味し、他の値はエラーを意味するという規則に従って評価する必要があります。

test[ ]、または[[ ]]演算子を使用すると、bash条件は、終了コード0(/ bin/trueの結果)の場合にtrueと評価されます。それ以外の場合は、偽と評価されます。

文字列は、終了コードとは異なる方法で評価されます。

if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi

if [ -z "" ] ; then echo null ; fi

(( ))算術演算子は、1と0をtrueとfalseとして解釈します。ただし、その演算子をtest[ ]、または[[ ]]の完全な代替として使用することはできません。算術演算子がいつ役立つかを示す例を次に示します。

for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
  if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done
15
Philippe A.

0終了コードが成功を意味するのは単なる慣例です。 EXIT_SUCCESS は、ほとんどすべての最新システムで0になります。

編集:

「テスト0とテスト1の両方が0(success)?

それはまったく別の質問です。答えは、テストに単一の引数を渡すと、その引数がヌル文字列( "")でない限り常に成功するということです。 Open Group documentation を参照してください。

15

通常、プログラムは成功するとゼロを返し、失敗するとゼロ以外を返します。 falseは便利なゼロ以外の値であるため1を返しますが、一般的にゼロ以外の値は何らかの障害を意味し、多くのプログラムはさまざまな障害モードを示すためにさまざまなゼロ以外の値を返します。

12
Michael Mrozek

私の知る限り、成功した場合は0を返す必要があるというCの規則に基づいています。見る:

man close

ほとんどのC(POSIX)APIはこのようにビルドされます。 http://en.wikipedia.org/wiki/C_POSIX_library

4
mathk

これは、Unixの初期に遡る慣習です。

慣例により、すべてのシステムコールは、成功した場合は0を返し、そうでない場合はゼロ以外を返します。異なる番号を使用して、失敗の異なる理由を示すことができるためです。

シェルはこの規則に従います。0は最後のコマンドが成功したことを意味し、そうでない場合はゼロ以外を意味します。同様に、ゼロ以外の戻り値は、出力エラーメッセージに役立ちます。 1:「脳死」、2:「無情」など。

3
user1252446

真/偽を成功/失敗と同一視しようとしている。

それらは完全に2つですが、最初は微妙ですが、異なる二分法です!

シェルスクリプトでは、true/falseなどはありません。シェルの「式」は真/偽として解釈されません。むしろ、シェルの「式」は成功または失敗するプロセスです。

明らかに、プロセスは多くの理由で失敗する可能性があります。したがって、失敗の可能性をマッピングするために、より大きなセットコードが必要です。正の整数がトリックを行います。一方、プロセスが成功した場合、それはそれがすべきことを正確に行ったことを意味します。それを行う方法は1つしかないため、必要なコードは1つだけです。 0はトリックを行います。

Cでは、プログラムを作成しています。シェルスクリプトでは、何かを成し遂げるために多数のプログラムを実行しています。

差!

3
captaincurrie

それを覚えるのに良い方法かもしれません:

  • リターンコードは「答えは何ですか?」と答えます。 true(またはその他の結果)またはfalse
  • 終了コードは「問題は何ですか?」と答えます。終了コードまたは問題なし(0)
1
jjisnow