bashスクリプトを記述するとき、&&と同等のものは何ですか?


31

これが重複する質問である場合は、事前に謝罪します。ここで質問する前に、検索/確認する努力をしました。

私はこのようなワンライナーを書くのに慣れています:

foocommand && foocommand2 && foocommand3

前のコマンドが「成功」した場合にのみ、後続のコマンドを実行したいという考えです。

私はやや長いスクリプトを書いていますが、このワンライナーは、誰にとっても混乱を招くコードの巨大なブロックのように見えるため、実行不可能です。

スクリプト内でコマンドの間隔を空け、それらの間にコメントを書きたいと思います。どうすればこれを行うことができますが、&&と同等のものがそこにありますか?


4
これは繰り返しクマ:&&以前の場合は、後続のコマンドが実行されるという意味ではありません1が成功しました。これは、コマンドリスト内の以前のすべてのコマンドの結果が成功した場合にコマンドが実行されることを意味します。あなたはこれを知っているかもしれませんが、将来の読者は誤解するかもしれません。
小次郎

1
また、単なる注意として、あなたが記述しているこの動作は||&&|または&)とは対照的に、短絡と呼ばれます。後者の演算子で使用される動作は、熱心な評価と呼ばれます。
-AndyPerfect

7
@kojiro:区別はありません。a && b && cのみ実行されますb場合はa成功します「それだけで動作しますので、c場合bと、」それだけで走る成功「c場合ab:成功の両方の」同等のステートメントあるb場合を除き、成功することはできませんa成功しました。
-ruakh

1
@ruakhの方a || b && cがわかりやすいです。
小次郎

8
@ruakhいいえ、true || false && echo hi出力しますhi仕様には、 演算子「&&」および「||」が記載されています 等しい優先順位を持ち、左結合性で評価されます。
小次郎

回答:


23

次のようにできます:

#!/bin/sh
ls -lh &&
    # This is a comment
    echo 'Wicked, it works!'

あなたが正しく尋ねたことを理解したと思います。


ありがとう。これは、私が望んでいたことに最も近いものです。また、必要に応じて1つのライナーに簡単に変換できます。
マイクB

マイク、あなたはコードのクリーンさを心配しているので、一般的な慣習はチェーンの2-Nセクションを最初のインデントの下にインデントすることです。
jblaine

@jblaineあなたが何を言っているのか理解できません。詳しく説明してもらえますか?
マイクB

マイク、Stackexchangeでは回答を適切に書式設定できないため、ここですべてを説明します。インデント
-jblaine

@jblaine良い点、行をインデントするように編集。
フォルカーシーゲル14

38

あなたはシバンラインを変更することができます

#!/bin/bash -e

エラーが発生すると、スクリプトは停止します。


1
面白い。ちゃんと覚えておきますよ。ありがとうございました。
マイクB

必要なときにset -eを入力する
手間を省く

@Silverrocker POSIXでもあります(bashもちろん一部を除く)。POSIXシェルは、に適用可能な多くのオプションを取りますset。またはその逆?setスクリプト内でシェルコマンドラインオプションを設定する方法です。
カズ

7
残念ながら、通常の終了ステータスの規則に従わない標準的なユーティリティが多数あり、-e誤動作する可能性があります。たとえば、diff2つの同一でないファイルを作成するたびにスクリプトを終了させたくないでしょう。もちろん、このようなコマンドに追加|| true(または|| [ $? = 1 ])することでこれを回避できますが、OPはこのスクリプトを読まなければならない「他の人」に言及し、「他の人」はおそらく、に対処する-e
-ruakh

4
-e私の会社のある管理者がを使用してスクリプトを起動し続けるまで、私はかつて彼女を強打bash myscript.shしました-e。これで、すべてのスクリプトset -eに2行目が追加されました。
カルロスキャンデロス

19

set -eアイデアが気に入らない場合は、ロジックを逆にすることができます。

foocommand || exit 1
foocommand2 || exit 2
foocommand3 || exit 3

さらに便利exitなのは、有用なエラーメッセージを出力するものに置き換えてから終了することです。関数内では、もちろん、のreturn代わりに必要ですexit


11
またはfoocommand || exitfoocommandゼロ以外の場合、の終了ステータスで終了します。
ステファンシャゼル

これはどのように作動しますか?Cのようですか?左の引数がTRUEと評価されると、それ以上の引数はチェックされませんか?
ヴォラック

はい、そうです。これは、Lisp(および関数型言語全般、私が思うに)およびPerlの一般的なイディオムです。
トリプリー

9

if else fi代わりにブロックを使用できます。

if foocommand; then

  # some comments

  if foocommand2; then

    # more comments

    foocommand3
  fi
fi

少し読みやすくなっています。

または\、大きな1ライナーをいくつかの行に分割するために使用できます

foocommand && \
  # some comment
  foocommand2 && \
    # more comment
    foocommand3

しかし、もちろん、これは訓練されていない目にとって混乱を招く可能性があります。


4
私は\そこに必要だとは思わない。
サミュエルエドウィン区

あなたが正しいです。習慣の力。
マルティンキャナバル

5

ネストされたifステートメントの使用を検討できます。他のオプションは、カーリーを使用してグループ化することです{ true && echo hi; } || echo huh

更新1:

改行/コメントのない例を次に示します。

{ { false && echo "inner true"; } && { echo "inner true" && true; } || { echo "inner false" && false; } || echo "outter false"; }

@Stephaneセミコロンを追加していただきありがとうございます。電話を使って返信しているので、答えを二重にチェックしていません。:)
リビングスタッカート

面白いアイデア。入れ子になったifステートメントを考えていましたが、たくさんのものをつなぎ合わせていると、面倒になるかもしれません。
マイクB

4

コマンドの各シーケンスを機能に分割します。

big_block_1() {
  # ...
}
big_block_2() {
  # ...
}
big_block_3() {
  # ...
}

big_block_1 && big_block_2 && big_block_3

0

私はいつも「失敗」関数を書いて、失敗が起こったときにやろうとしていることを指定して、その||パターンを使うようにします。次のように:

function fail() {
  echo "Failure: ${@}"
  exit 1
}

foocommand || fail "couldn't foo"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.