Bash:如何在按下任意键的情况下结束无限循环?

jan*_*tin 25 bash while-loop

我需要编写一个无限循环,在按下任何键时停止.

不幸的是,只有在按下一个键时才会循环.

想法好吗?

#!/bin/bash

count=0
while : ; do

    # dummy action
    echo -n "$a "
    let "a+=1"

    # detect any key  press
    read -n 1 keypress
    echo $keypress

done
echo "Thanks for using this script."
exit 0
Run Code Online (Sandbox Code Playgroud)

sam*_*var 33

您需要将标准输入置于非阻塞模式.这是一个有效的例子:

#!/bin/bash

if [ -t 0 ]; then
  SAVED_STTY="`stty --save`"
  stty -echo -icanon -icrnl time 0 min 0
fi

count=0
keypress=''
while [ "x$keypress" = "x" ]; do
  let count+=1
  echo -ne $count'\r'
  keypress="`cat -v`"
done

if [ -t 0 ]; then stty "$SAVED_STTY"; fi

echo "You pressed '$keypress' after $count loop iterations"
echo "Thanks for using this script."
exit 0
Run Code Online (Sandbox Code Playgroud)

编辑2014/12/09:添加-icrnl标记以stty正确捕获Return键,cat -v而不是read为了捕获Space.

cat如果足够快地输入数据,则可能会读取多个字符; 如果不是所需的行为,请替换cat -vdd bs=1 count=1 status=none | cat -v.

  • @Thor84no 它是针对旧的、有缺陷的系统的一种保护措施:http://stackoverflow.com/a/6853353/111461 (2认同)

Pau*_*aul 7

read有一个-n可以使用的超时参数.对输入执行非阻塞检查,查看返回状态是否为0,如果是,则从循环中断.

-t 超时

如果在超时 秒内未读取完整的输入行,则会导致读取超时并返回失败 . 超时可以是十进制数,小数点后面的小数部分.此选项仅在读取 来自终端,管道或其他特殊文件的输入时有效; 从常规文件中读取时没有任何效果.如果timeout为0,如果输入在指定的文件描述符上可用,则read返回成功,否则失败.如果超出超时,则退出状态大于128.

  • 就像这样‘同时!读取-t0;执行 echo -n .; 完毕; 读; echo Finished`,但直到按下 Enter(或 Ctrl-d)后它才会完成,并且即使使用可能的“-s”选项,它也会回显输入,并且不考虑可能的“-d”选项。(GNU bash,版本 4.3.11) (2认同)

mou*_*iel 3

通常我不介意用简单的 CTRL-C 来打破 bash 无限循环。tail -f这是终止实例的传统方式。