Предположим, у нас есть простой цикл:
a=0 while (( a<5 )); do echo $a (( a++ )) done
На первый взгляд — все верно и должно работать. Давайте запустим:
$ cat plus #!/usr/bin/env bash echo -e "nFirst loopn" a=0 while (( a<5 )); do echo $a (( a++ )) done
$ ./plus First loop 0 1 2 3 4
Но — если мы добавим set -o errexit
то увидим совсем другую картину:
$ cat plus #!/usr/bin/env bash set -o errexit echo -e "nFirst loopn" a=0 while (( a<5 )); do echo $a (( a++ )) done
$ ./plus First loop 0
В debug-режиме всё будет выглядеть ещё интереснее:
$ bash -x plus + set -o errexit + echo -e 'nFirst loopn' First loop + a=0 + (( a<5 )) + echo 0 0 + (( a++ ))
Почему так? Давайте добавим вывод ошибок:
$ cat plus #!/usr/bin/env bash set -o errexit echo -e "nFirst loopn" a=0 while (( a<5 )); do echo $a (( a++ )) && { echo Report: $?; echo -e "PlusOKn"; } || { echo Report: $?; echo -e "PlusERRn"; } done
И запустим:
$ ./plus First loop 0 Report: 1 PlusERR
Как видим — при первой итерации выражение (( 0 + 1 ))
возвращает ошибку, из-за чего выполнение цикла и прерывается, т.к. установлена опция errexit
.
Решение — либо не использовать errexit
, либо — использовать другие арифметические выражения.
Вот несколько примеров:
$ cat plus #!/usr/bin/env bash #set -o errexit echo -e "nFirst loopn" a=0 while (( a<3 )); do echo $a (( a++ )) && { echo Report: $?; echo -e "PlusOKn"; } || { echo Report: $?; echo -e "PlusERRn"; } done echo -e "nSecond loopn" b=0 while (( b<3 )); do echo $b (( ++b )) && { echo Report: $?; echo -e "PlusOKn"; } || { echo Report: $?; echo -e "PlusERRn"; } done echo -e "nThrid loopn" c=0 while (( c<3 )); do echo $c c=$(( c+1 )) && { echo Report: $?; echo -e "PlusOKn"; } || { echo Report: $?; echo -e "PlusERRn"; } done echo -e "nFourth loopn" d=0 while (( d<3 )); do echo $d let "d=d+1" && { echo Report: $?; echo -e "PlusOKn"; } || { echo Report: $?; echo -e "PlusERRn"; } done
И выполнение — обратите внимание на отсутствие ошибок в остальных циклах:
$ ./plus First loop 0 Report: 1 PlusERR 1 Report: 0 PlusOK 2 Report: 0 PlusOK Second loop 0 Report: 0 PlusOK 1 Report: 0 PlusOK 2 Report: 0 PlusOK Thrid loop 0 Report: 0 PlusOK 1 Report: 0 PlusOK 2 Report: 0 PlusOK Fourth loop 0 Report: 0 PlusOK 1 Report: 0 PlusOK 2 Report: 0 PlusOK