次の書き方だと ./xxx.sh が 0 以外のときにそこで終了してしまうので case の後が実行されることはありません。
set -e
./xxx.sh $1
case $? in
1) echo one ;;
2) echo two ;;
*) echo unk ;;
esac
echo end
一時的に set +e して戻り値を変数に入れてから set -e に戻す方法が考えられますがイマイチです。
set -e
set +e
./xxx.sh $1
ret=$?
set -e
case $ret in
1) echo one ;;
2) echo two ;;
*) echo unk ;;
esac
echo end
次のようにすると上手くいきます。
set -e
./xxx.sh $1 &&:
case $? in
1) echo one ;;
2) echo two ;;
*) echo unk ;;
esac
echo end
解説
set -e は && や || でコマンドが繋げられた場合、リストの最後のコマンドが非 0 を返した場合だけ終了します。
./xxx.sh が 0 を返した場合、&& の後ろの : が実行されます。
: は何もせずに成功する組み込みコマンドなので、戻り値は 0 です。
よって $? は 0 です。
./xxx.sh が非 0 を返した場合、リストの最後ではないので set -e でも終了しません。
さらに && で繋がっているので : は実行されません。
よって $? は ./xxx.sh の戻り値そのままです。