Bash Math: 한 숫자가 다른 숫자로 나누어지는지 계산할 때 1이 틀리거나 오류가 발생함

Bash Math: 한 숫자가 다른 숫자로 나누어지는지 계산할 때 1이 틀리거나 오류가 발생함

나는 다음의 솔루션을 사용했습니다.이 답변내가 작성하고 있는 스크립트에서는 작동하지 않는 것 같습니다. 배쉬 5를 사용하고 있습니다. 이것은 단순화된 테스트 케이스입니다. do_thing함수가 5분의 배수로 호출되기를 원하지만( 실제 스크립트에서는 메인 프로그램 시작 부분에서 루프를 트리거하기 때문에 $min및 동일하지 않은 경우) 실행하면 또한 트리거됩니다. 이 Multiple + 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로 줄입니다.따라서 나머지를 다시 계산하면 항상 하나가 줄어듭니다. 당신은 "카운터"를 줄이고 있습니다앞으로원하는 계산을 수행하는 데 사용됩니다!

논리적으로 초 = 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 에 주의하세요 ||. 빠르고 지저분한 경우에는 괜찮지만, 복잡한 논리의 경우에는 속일 ​​수 있습니다!

이러한 논리 연산자는아니요대안이 있다고 하더라도 적절하게 테스트하십시오.때때로- 테스트 사용과의 한 가지 차이점은 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))
  ...

관련 정보