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
終了状態でなければなりません。then
else
化合物一覧実行されているか、実行されていない場合は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_3
はgrep
内部で文字列を検索しますgrep [OPTIONS] PATTERN [FILE...]
。実際にこれを見てください:input.txt
input.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
拡張ファイル名のみが検索され、不要な結果が表示されます。