如何读取超时而不让 bash 认为这是错误?

如何读取超时而不让 bash 认为这是错误?

我有一个 read_user_input.sh 脚本:

#!/bin/bash

# set -e

prompt="bla? [Y/n] "

while true; do
    read -p "$prompt" -n 1 -s -t 3 reply
    case $reply in
        ""|Y|y) echo "bla!!!"; break;;
        N|n) echo "no bla :( you suck"; break;;
        *) ;;
    esac
done

正如我预期的那样工作 - 即

  • 用户输入“Y”->bla
  • 用户输入“y”->bla
  • 用户按 Enter -> bla
  • 超时 -> bla

但是,添加时set -e- 读取以错误> 128结束。

read --help

Exit Status:

返回代码为零,除非遇到文件结束、读取超时(这种情况下它大于 128)、发生变量分配错误或者向 -u 提供了无效的文件描述符作为参数。

克服这个问题的最佳方法是什么?

  1. 添加|| true似乎不正确,因为它会隐藏任何真正的错误。
  2. 我也不想删除set -e
  3. 我想到另一件事就是处理它,trap但这似乎有点过头了

答案1

如果发生超时,则不要添加|| true,而是将设置$reply为:y

    read -p "$prompt" -n 1 -s -t 3 reply || {
        err=$?
        if (( $err > 128 )) ; then
            reply=y
        else
            exit $err
        fi
    }

答案2

这里有一个 hack,使用命令替换来分叉一个-e未启用的子 shell。

#!/bin/bash

set -e

prompt="bla? [Y/n] "

while true; do
    case $(read -p "$prompt" -n 1 -s -t 3 reply; echo $reply) in
        ""|Y|y) echo "bla!!!"; break;;
        N|n) echo "no bla :( you suck"; break;;
        *) ;;
    esac
done

答案3

使用@choroba 答案,我将 switch case 更改为:

#!/bin/bash

set -e

prompt="bla? [Y/n] "

while true; do
    read -p "$prompt" -n 1 -s -t 3 reply || (( $? > 128 ))
    case $reply in
        ""|Y|y) echo "bla!!!"; break;;
        N|n) echo "no bla :( you suck"; break;;
        *) ;;
    esac
done

相关内容