コマンドベースのif文

コマンドベースのif文

ifコマンドの実行方法は次のとおりです。

$if echo test | grep st ; then echo yes ; fi ; echo $?
test
yes
0

よさそうだね不一致で試してみましょう。

$if echo test | grep 123 ; then echo yes ; fi ; echo $?
0

そうではありません。ステートメントはif正常に実行されますが、ゼロ終了コードを返します。

誰かが私にこれを説明できますか?

答え1

$?afterifブロックにはステートメントの終了ステータスが含まれていますif。基準指定する

コマンドの終了状態はまたはif終了状態でなければなりません。thenelse 化合物一覧実行されているか、実行されていない場合は0です。

最初の場合は、コマンドの終了ステータスが表示されますecho yes。 2番目の場合、thenまたはブロックelseでコマンドが実行されないため、終了ステータスは0です。

答え2

Bashのマニュアルで(フォーマットとハイライトを追加):

リストであればリスト。リストなら] ... [他のリスト]

リストが実行されると。終了ステータスが 0 の場合、then リストが実行されます。それ以外の場合は、各 elif リストが順番に実行され、終了ステータスが 0 の場合、対応する then リストが実行され、コマンドが完了します。それ以外の場合は、elseリストがある場合に実行されます。終了状態は、最後に実行されたコマンドの終了状態です。条件が真にテストされていない場合はゼロです。

したがって、終了状態を理解することが重要です。実際に見ています。あなたの例では、echo test | grep 123最後のコマンドは正常に終了しませんでした。これを最初に実行してから終了ステータスをテストすると、ゼロ以外の終了grepステータスを返すことがわかります。

$ grep 'noexist' /etc/passwd
$ echo $?
1

対照的に、if文は条件としてのコマンドがtrueかどうかをテストしないので、仕様とマニュアルによると、終了ステータスは0です。

grep '123'ただし、現在のディレクトリにファイル123がある場合は、引用符で囲まれていないパターンが原因で他の問題が発生する可能性があります。


grepと引用パターンに関する注意

スティーブンジッタコメント最後の段落の説明。これは必ずしもこの質問の主題とは無関係であり、すでに取り上げています。ここ、同様の質問に答えた。ここ、しかし興味深いので、別の方向に行きます。 2つの例を見てみましょう。

grep inputこれには引用符のない単純な文字列があります。grep構文は、最初の文字列をパターンとして扱うことです。ここでは問題ありません。次のように動作します。

bash-4.3$ strace -e trace=execve grep input <<< "this is input line"
execve("/bin/grep", ["grep", "input"], [/* 80 vars */]) = 0
this is input line
+++ exited with 0 +++

しかし、正規表現(あなたが考えるもの)がある場合は、何が起こるのかを確認してください。

bash-4.3$ strace -e trace=execve grep input* <<< "this is input line"
execve("/bin/grep", ["grep", "input.txt", "input.txt.bak"], [/* 80 vars */]) = 0
+++ exited with 1 +++

シェルはユーザーを表示し、*パス名拡張を実行します。シェルによって実行される実際のコマンドは次のとおりです。構文に応じて、コマンドgrep some_file_1 some_file_2 some_file_3grep内部で文字列を検索しますgrep [OPTIONS] PATTERN [FILE...]。実際にこれを見てください:input.txtinput.txt.bak

bash-4.3$ echo "I have input.txt here" > input.txt.bak
bash-4.3$ grep input* <<< "this is input line"
I have input.txt here

入力文字列は完全に無視され、grep拡張ファイル名のみが検索され、不要な結果が表示されます。

関連情報