if else ステートメントは論理および&&または||どのような点で他のものよりも優先すべきですか?

if else ステートメントは論理および&&または||どのような点で他のものよりも優先すべきですか?

意思決定構造について学んでいますが、次のコードを見つけました。

if [ -f ./myfile ]
then
     cat ./myfile
else
     cat /home/user/myfile
fi


[ -f ./myfile ] &&
cat ./myfile ||
cat /home/user/myfile

どちらも同じように振る舞います。ある方法を他の方法よりも使用すると、どのような利点がありますか?

答え1

ほとんどの人はフォーマットを理解する方が簡単だと思いますifthenelsefi

の場合はtrueが返されることをa && b || c確認する必要があります。bこれは微妙なエラーの原因であり、このスタイルを避けるべき理由です。b が true を返さない場合、同じではありません。

 $ if true; then false ; else echo boom ; fi
 $ true && false || echo boom
 boom

長さが短くなることは、非常に短いテストとelse句のない作業に適しています。

 die(){ printf "%s: %s\n" "$0" "$*" >&2 ; exit 1; }

 [ "$#" -eq 2] || die "Needs 2 arguments, input and output"

 if [ "$#" -ne 2 ] ; then
     die "Needs 2 arguments, input and output"
 fi

&&そして||そうです。short circuiting operators結果がわかったら、不要な追加テストはスキップされます。a && b || cにグループ化されます(a && b) || c。終了ステータス0を返さないように定義されている場合afailsグループは既知のものであるため、実行する必要はありません。式の結果がわからないため、実行が必要です。成功すると(0を返す)、演算子はまだ結果がわからないため、調べるために実行する必要があります。成功すれば成功し、結果全体が成功したことが知られているので、実行する必要はありません。失敗すると、式の値がまだわからないため、実行する必要があります。(a && b)failb||ca&&a && bbba && b||cb||c

答え2

いいえ、構造if A; then B; else C; fiA && B || Cはい。等しくない

を使用すると、if A; then B; else C; fiコマンドは常に評価され実行されますA(少なくとも実行を試みた場合)。その後、コマンドBまたはコマンドが評価され実行されます。C

A && B || Cコマンドの場合は同じですAが異なります。次の場合、Bコマンドは評価され実行されます。CC誰でも A失敗するまたは B失敗する。

あなたの例であなたを想定すると、成功chmod u-r ./myfileにもかかわらず[ -f ./myfile ]cat /home/user/myfile

私のアドバイス:読みやすく理解しやすく、問題のない必要なものを使用またはA && B使用してください。A || Bただし、if...then...else...thenを意味する場合は、を使用してくださいif A; then B; else C; fi

答え3

オペレーター&&前のコマンドが正常に実行されたら、次のコマンドを実行します(終了コード($?)0 =論理trueを返します)。

フォームA && B || C、コマンド(または条件)評価され、返品本物(成功、終了コード0) 次のコマンド第二処刑される。もし失敗(それで返されます)間違った- ゼロ以外の終了コード)および/または第二失敗(返品間違った) 次にコマンド実行されます。

演算子は次のよう&&に使用されます。そして条件チェックと演算子は||次のように動作します。または状態確認中です。

スクリプトで実行したい操作に応じて、A && B || Cフォームを条件付きチェック(例など)に使用したり、コマンドをリンクしたり、前のコマンドに成功した終了コードがある場合は、一連のコマンドを実行したりできます。0
そのため、次のコマンドを頻繁に表示できます
do_something && do_something_else_that_depended_on_something

例:
apt-get update && apt-get upgrade アップデートが失敗した場合、アップグレードは実行されません(実際の環境では話します...)。

mkdir test && echo "Something" > test/file
echo "Something"このセクションは成功し、ジョブが終了コードを返した場合にのみ実行されます。mkdir test0

./configure --prefix=/usr && make && sudo make install
通常、必要な依存関係コマンドを一緒にリンクしてジョブをコンパイルするときに検出されます。

上記の「チェーン」を使って達成しようとするともし-それから-その他単純な作業では、より多くのコマンドとチェックが必要になります(したがって、書き込む必要があるコードも多くなり、間違っている可能性があります)。

また、リンクされたコマンドを覚えておいてください。&&そして||シェルに基づいて左から右に読みます。次のステップが以前のコマンドの一部の出力に依存するように、コマンドと条件付きチェックを角括弧でグループ化できます。たとえば、次のように見てください。

root@debian:$ true || true && false;echo $?
1 
#read from left to right
#true OR true=true AND false = false = exit code 1=not success

root@debian:$ true || (true && false);echo $?
0 
# true OR (true AND false)=true OR false = true = exit code 0 = success

または実際の例は次のとおりです。

root@debian:$ a=1;b=1;c=1;[[ $a -eq 1 ]] || [[ $b -eq 1 ]] && [[ $c -eq 2 ]];echo $?
1 
#condition $a = true OR condition b = true AND condition $c = false
#=> yields false as read from left to right, thus exit code=1 = not ok

root@debian:$ a=1;b=1;c=1;[[ $a -eq 1 ]] || [[ $b -eq 1 && $c -eq 2 ]];echo $?
0 
#vars b and c are checked in a group which returns false, 
#condition check of var a returns true, thus true OR false yields true = exit code 0

一部のコマンドは、実行されているプロセスによって異なる終了コードを返すか、その操作に応じて別のコードを返します(たとえば、GNUコマンドはdiff次を返します)。12つのファイルが異なる場合0そうでない場合)。これらのコマンドは慎重に取り扱う必要があります。&&そして||

また、パズルのすべての部分を1つに合わせるには、演算子を使用してコマンドをリンクすることに注意してください;。フォーマットを使用すると、A;B;Cコマンドと終了コードに関係なく、すべてのコマンドが実行され続けます。AB

答え4

これについてのほとんどの混乱は、おそらくbashドキュメントで次を呼び出すという事実によるものです。ANDとORのリスト。角かっこ内の角かっこ&&と論理的に似ていますが、||機能は異なります。

いくつかの例がこれを最もよく説明しています。

注:単一および二重角括弧([ ... ]および[[ ... ]])自体は、比較を実行して終了コードを返すコマンドです。彼らは実際には必要はありませんif

cmda  && cmdb  || cmdc

cmdatrue で終了するとcmdb実行されます。
cmda出口が false の場合、実行されずにcmdb実行cmdcされます。

cmda; cmdb  && cmdc  || cmdd

終了方法はcmda無視されます。
cmdbtrue で終了するとcmdc実行されます。
cmdbシャットダウンがfalseの場合、実行されずにcmdc実行cmddされます。

cmda  && cmdb; cmdc

cmdatrueで終了したらcmdb実行してから実行しますcmdc
終了がcmda偽の場合はcmdb実行しないしかしcmdc、。

ああ?彼はなぜcmdc処刑されたのですか?
インタプリタにはセミコロン( ;)と改行文字がまったく同じ意味を持つからです。 Bashはこのコード行を次のように扱います。

cmda  && cmdb
cmdc  

cmdb; cmdc目的の効果を得るには、中かっこで囲む必要があります。複合命令(グループ命令)。追加の終了セミコロンは{ ...; }構文要件にすぎません。だから私たちは...

cmda && { cmdb; cmdc; }
cmdatrueで終了したらcmdb実行してから実行しますcmdc
cmda出口が false の場合、cmdbまたは両方はcmdc実行されません。
実行は次の行まで続きます。

使用法

条件付きコマンドのリストは、関数ができるだけ早く返すのに最も便利であるため、解釈および実行する必要のある不要なコードを多く防ぐことができます。ただし、複数の関数を返すことは、すべての可能な条件をより簡単に処理できるように、関数を短く保つように努力する必要があることを意味します。

以下はコード実行の例です。

fnInit () {
  :
  _fn="$1"
  ### fnInit "${FUNCNAME}" ...
  ### first argument MUST be name of the calling function
  #
  [[ "$2" == "--help-all" ]]  && { helpAll                      ; return 0; }
  ### pick from list of functions
  #
  [[ "$2" == "--note-all" ]]  && { noteAll                      ; return 0; }
  ### pick from notes in METAFILE
  #
  [[ "$2" == "--version"  ]]  && { versionShow "${_fn}" "${@:3}"; return 0; }
  #
  [[ "$2" == "--function" ]]  && {
    isFnLoaded "$3"           && { "${@:3}"                     ; return 0; }
    #
    errorShow functionnotfound "Unknown function:  $3"
    return 0
  }
  ### call any loaded function
  #
  [[ "$2" == "--help" || "$2" == "-h" ]]  && { noteShow "$_fn" "${@:3}"; return 0; }
  ### fnInit "${FUNCNAME}" --help or -h
  #
  return 1
}

関連情報