$?ifステートメント


12
function foo {
   (cd $FOOBAR;
   <some command>
   if [$? -ne 0]
   then
      echo "Nope!"
   else
      echo "OK!"
   fi
   )
}

上記のような関数を記述して.bashrcファイルに配置しようとしています。ファイルを入手して実行すると、次のようになります。

合計時間:51秒
-bash:[1:コマンドが見つかりませんでした

誰かが私が間違ったことを理解するのを手伝ってくれる?


4
場合のテスト$?ISは、0に等しいif声明、無意味であるifコマンドを期待している場合、コマンドのリターンを述べ0、それがブロック内のコードを実行します。そのif true; then echo hello; fiコマンドはエコーされますので、ハローtrue返さ0
llua 14

1
@lluaそれは無意味ではありません。ステートメントの()コマンドではない$?、最後のパイプラインのステータスを保持します。例では、成功したかどうかをテストしています。and でも同じことができますが、と比べて長くて判読できない行を作成する可能性があります。同じことがtest[ifsome command&&||if [ $? -eq 0 ]if some command
当てはまり

@bonsaiviking何が$?拡張されるかはよく知っtestています。使用されていることに意味がないことを指摘しています。なぜならif some command、1つのステートメントで同じことを行うのに対して、2つの別個のステートメントを使用するからです。コマンドがすでに長い場合は、さらに3文字を追加しても、「判読不能」がひどく「判読不能」になることはありません。
llua 14

回答:


33

の後にスペースを追加し、その[前にスペースを追加します]

function foo {
   (cd $FOOBAR;
   <some command>
   if [ $? -ne 0 ]
   then
      echo "Nope!"
   else
      echo "OK!"
   fi
   )
}

[それだけのようなコマンドで、シェルの組み込みでechoreadexpr...それはそれの後にスペースを必要とする、とのマッチングが必要です]

書き込みは[ $? -ne 0 ]、実際に起動され[、それに4つのパラメータを与える:$?-ne0、と]

注:エラーが表示されるという事実は、の値があったことを[1: command not found意味し$?ます1


1
Linux VMであなたの答えが正しいことを確認しました。
サミア14

[test同様にリンクです
リッキービーム

2
ほとんどのシェルの@RickyBeamは[組み込みシェルであり、/usr/bin/[めったに使用されません。
Patrick 14

20

または、$?完全にスキップすることもできます。コマンドがのcmd場合、以下が機能するはずです。

function foo {
   (cd $FOOBAR;
   if cmd
   then
      echo "OK!"
   else
      echo "Nope!"
   fi
   )
}

6

使用する前に変数に戻り値を割り当てることをお勧めします

retval="$?"
if [ $retval -ne 0 ]

戻り値を再利用できます。たとえば、if ... elif ... else ...ステートメントで。


-1:後にスペースを忘れました[(スペースがないと、で構文エラーになります)エラーbashを編集して修正すると元に戻ります。
サミア14

はい、そうです。それを私が直した。
Abdul

最後のコメントがあなたに向けられた
@samiam

4
:)あなたの答えを少し広げてもらえますか?なぜそれが良い習慣なのですか?どのような種類のエラーを回避できますか?
terdon

1
@terdon $?後でスクリプトを編集するときにコマンドと$?チェックの間に行を入れると壊れてしまうため、直接使用することは悪い習慣です。
サミア14

3

コマンドの$?引数として[(その[コマンドがifステートメントの条件部分で実行されるかどうかにかかわらず)使用する唯一の理由は、次のような特定の戻りステータスを区別したい場合です。

until
  cmd
  [ "$?" -gt 1 ]
do
  something
done

すべての人のための構文はifwhileuntil...文は、

if cmd-list1
then cmd-list2
else cmd-list3
fi

成功したかcmd-list2どうかに関係なく実行されます。cmd-list1cmd-list3

[ "$?" -eq 0 ]コマンドは何もしません。$?が0の場合$?は0 に設定され、$?ゼロ以外の場合はゼロ以外に設定されます。

cmd失敗したときに何かを実行したい場合は、次のようになります。

if ! cmd
then ...
fi

一般に、$?どの値がtrueまたはを意味するかは言うまでもなく、いじくる必要はありませんfalse。特定の値を区別する必要がある場合、または後で保存する必要がある場合(たとえば、関数の戻り値としてそれを返す場合)は、次のような唯一のケースです。

f() {
  cmd; ret=$?
  some cleanup
  return "$ret"
}

また、変数を引用符で囲まないままにすることは、split + glob演算子であることも覚えておいてください。ここでその演算子を呼び出すことは意味がないため、次のようにする必要があります。

[ "$?" -ne 0 ]

ないことは言う[ $? -ne 0 ]までもありません[$? -ne 0 ](たまたま最初の文字が含まれている[場合にのみコマンドが呼び出さ$IFSれます$?)。

また、関数を定義するBourneの方法function-name()は、コマンドの前にくることです。これは、シェルのようなすべてのボーン場合を除き、だbashyash(との最近のバージョンposh)のみ(化合物のコマンドはされる化合物のコマンドを許可する{...}か、(...)またはのようなものfor...doneif...fi...

function foo { ... }あるksh関数定義の構文は次のとおり。ここで使用する理由はありません。

コードは移植可能(POSIXly)に記述できます。

foo() (
  cd -P -- "$FOOBAR" || return # what if the cd failed!
  if
    <some command>
  then
    echo 'OK!'
  else
    echo 'Nope!'
  fi
)

また、注意してcdなくて-P、非常に特別な意味(含まれているハンドルパス持つ..他のコマンドとは異なるコンポーネントを)、それは避けて混乱にスクリプトに含める方が良いですので。

(この関数はfalsecd失敗した場合は戻りますが、失敗した場合は戻りませ<some command>ん)。


1

以下のコマンドで、必要なすべてを1行で実行できると思います。

(( verify = $?!=0?'Nope!':'OK!' ))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.