Bash Math:ある数字が別の数字に分割されているかどうかを計算すると、1が間違っているかエラーが発生する

Bash Math:ある数字が別の数字に分割されているかどうかを計算すると、1が間違っているかエラーが発生する

私は次の解決策を使用しました。この回答私が書いているスクリプトではうまくいかないようです。バッシュ5を使用しています。これは単純化されたテストケースです。do_thing関数は5分の倍数で呼び出されることを望んでいます(実際のスクリプトではメインプログラムの先頭でループをトリガーするため、$min同じでない場合)、実行するとトリガーされます。これはMultiple + 1なので、明らかにどこかに1つずつ、または数学エラーが少ししか表示されません。どんなアイデアがありますか?$minutesdo_thing

#!/usr/bin/env bash

minutes=6
sec=00
min="$minutes"

do_thing() {
  echo 'done thing'
}

while [ "$min" -ge 0 ]; do
  remainder=$(( min % 5 ))
  # TODO: this is broken
  [ "$remainder" -eq 0 ] && [ "$min" -ne "$minutes" ] && do_thing
  while [ $sec -ge 0 ]; do
    echo "$min $sec"
    ((sec=sec-1))
    sleep 1
  done
  sec=59
  ((min=min-1))
done

ベストアンサー1

set -xBashスクリプトをデバッグするときに最初にすべきことは、一番上に追加することです。これにより、スクリプトが実行する操作、ループの各反復で各テストの外観などを確認できます。

私が置く場所は次のとおりです。

#!/usr/bin/env bash

# NOTE: Remove or comment the below line when you're done debugging!
set -x

minutes=6
sec=00
...

デバッグ中にコード全体に分散させると、echo "myvar = $myvar"スクリプトの主要ポイントで変数の値を追跡して、予想される値と比較できます。

論理の欠陥は、一度「分カウンタ」ループを終了できる条件を取得すると、すぐに最小値を1に減らします。したがって、残りを再計算すると、常に1つが減ります。 「カウンター」を減らしています今後希望の計算を実行するために使用されます!

論理的に秒= 0をテストしたいと思います。それから残りを計算し、それから次のループを設定します。

#!/usr/bin/env bash

#set -x

minutes=6
sec=00
min="$minutes"

do_thing() {
  echo 'done thing'
}

while [ "$min" -ge 0 ]; do
  while [ $sec -ge 0 ]; do
    echo "$min $sec"
    ((sec=sec-1))
    sleep 1
  done
  remainder=$(( min % 5 ))
  # Added echo for debugging
  echo "remainder = $remainder"
  [ "$remainder" -eq 0 ] && [ "$min" -ne "$minutes" ] && do_thing
  sec=59
  ((min=min-1))
done

ここでまた目立つ点は――非常に&&andに注意してください||。高速で汚れた場合は問題ありませんが、複雑なロジックの場合はだますことができます!

これらの論理演算子はいいえ選択肢があるとしても、適切にテストしてください。時々- テストの使用との違いの1つは、if []; then...終了コードを自動的に使用することです。注意深く読み、()必要な作業順序を適用するために使用しないで、複数を連続して使用しないでください。

私のアドバイスを受け入れてここを避けたい場合は、&&次の方法があります(ネストされた `if は別の方法ですが、必要でなければ使用しないことをお勧めします)。

  ...
  remainder=$(( min % 5 ))
  # Added echo for debugging
  echo "remainder = $remainder"
  if ([ "$remainder" -eq 0 ] && [ "$min" -ne "$minutes" ]); then
    do_thing
  fi
  sec=59
  ((min=min-1))
  ...

おすすめ記事