루프에서 벗어날 때 0이 아닌 종료 코드가 트리거됩니다.

루프에서 벗어날 때 0이 아닌 종료 코드가 트리거됩니다.

일련의 작업을 실행하고 그 중 하나라도 실패하면 중지하고 싶었기 때문에 다음과 같이 썼습니다.

for task in [TASKS]; do
  process "$task" || break
  commit "$task"
done

이것은 잘 작동하지만 (예:지정됨) 일찍 중단하더라도 루프의 종료 상태는 0입니다. 이상적으로 break-ing은 실패를 전달할 수 있습니다.

0반환이 문서화된 동작이라는 것을 알고 있지만 break상대적으로 깔끔한 해결 방법이 있는지 궁금합니다. 내가 상상할 수 있는 최선의 방법은 이를 함수로 감싸서 didBreak변수를 설정하고 이를 (함수의) 종료 상태로 사용하는 것입니다. 작동하지만 지나치게 복잡하다고 느껴집니다.

답변1

이는 많은 쉘에서 사용될 수 있습니다 ! break(pdksh 기반 쉘 및 shFreeBSD 쉘 제외(통과 설계) 내 테스트에서):

$ zsh -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ bash -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ ksh88 -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ ksh93 -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ dash -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ yash -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ bosh -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
1
$ pdksh -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
0
$ mksh -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
0
$ posh -c 'for i in x; do ! break; echo "$i"; done'; echo "$?"
0

errexit어느 쪽에서도 실행 되지 않습니다 .

그것은austin-group(POSIX 뒤에 있는 기관) 메일링 리스트에 대해 토론하세요.작년. ( boshFreeBSD sh및 NetBSD 관리자 가 포함된) 논의는 sh합의에 도달하기 전에 끝났지만 일반적인 견해는 POSIX가 !명령의 종료 상태를 부정함으로써 문서화된 대로 이 동작을 요구했으며 break이는 명령의 종료 상태를 부정하는 특별한 내장 명령이라는 것이었습니다. 0 종료 상태로 종료합니다.

그러나 예를 들어 동일한 추론을 적용하면 return계산서에 맞는 껍질이 더 적다는 것을 알게 될 것입니다.

에서는 대신 익명 함수를 zsh사용할 수 있습니다 .returnbreak

$ () for i in x y; do echo $i; return 1; done
x
$ echo $?
1

답변2

당신은 다음과 같은 것을 할 수 있습니다

failed=false
for task in "${tasks[@]}"; do
  if ! process "$task"; then
      failed=true
      break
  fi
  commit "$task"
done

if "$failed"; then
   echo "Failed something" >&2
fi

답변3

내가 상상하는 해결책은 다음과 같다.

run_til_failure() {
  local didBreak=0
  for task in [TASKS]; do
    process "$task" || { didBreak=1; break; }
    commit "$task"
  done
  local loopExit=$?
  if (( loopExit )); then return $loopExit; fi
  return $didBreak
}

관련 정보