POSIX 替代 bash 读取超时和字符限制
POSIX alternative to bash read with timeout and character limit
我正在编写一个交互式 shell 脚本,需要在尽可能多的系统上 运行。是否有替代方法来实现与标准 POSIX 系统兼容的以下内容?
#! /bin/bash
echo -n "Do you wish to continue? (Y/n) 5 seconds to respond... "
read -n 1 -t 5 answer # accepts a single character, 5 second timeout.
if [ "$answer" = "n" ] || [ "$answer" = "N" ] ; then
echo -e "\nExiting..."
exit
fi
echo -e "\nContinuing with script..."
# More code
read
的超时对我来说最重要 (read -t 5
)。读取的一个字符限制是可取的,但不是必需的 (read -n 1
)。
理想情况下,该脚本可以在 POSIX 系统上运行,也可以在 bash 内运行,而无需启用特殊的 POSIX 兼容模式。
stty
program provides the means to do this. xterm
有几个脚本(在其源代码的 "vttests" 子目录中)保存、修改和恢复终端设置以允许它读取终端对转义序列的响应。下面是dynamic2.sh
的一部分(开头设置printf
或echo
,用来解决一些旧系统用$CMD
变量):
echo "reading current color settings"
exec </dev/tty
old=`stty -g`
stty raw -echo min 0 time 5
original=
for N in $FULL
do
$CMD $OPT "${ESC}]$N;?^G${SUF}" > /dev/tty
read reply
eval original$N='${reply}${SUF}'
original=${original}${reply}${SUF}
done
stty $old
if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null
then
trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM
else
trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15
fi
根据 Dickey 先生的回答调整 stty 设置,如果按下 'n' 或 'N' 以外的任何内容,以下内容似乎有效并继续执行脚本。
据我所知,所有的 stty 设置都是 posix。
#!/bin/sh
read_char() {
old=$(stty -g)
stty raw -echo min 0 time 50
eval "=$(dd bs=1 count=1 2>/dev/null)"
stty $old
}
printf "Do you wish to continue? (Y/n) 5 seconds to respond..."
read_char answer
# answer=$(getch)
# answer=$(getche)
if [ "$answer" = "n" ] || [ "$answer" = "N" ] ; then
printf "\nExiting...\n"
exit
fi
printf "\nContinuing with script...\n"
替代"read_char":
这避免了使用 eval(可能不安全)
getch() {
old=$(stty -g)
stty raw -echo min 0 time 50
printf '%s' $(dd bs=1 count=1 2>/dev/null)
stty $old
}
这避免了 eval 并打印按下的键
getche() {
old=$(stty -g)
stty raw min 0 time 50
printf '%s' $(dd bs=1 count=1 2>/dev/null)
stty $old
}
我正在编写一个交互式 shell 脚本,需要在尽可能多的系统上 运行。是否有替代方法来实现与标准 POSIX 系统兼容的以下内容?
#! /bin/bash
echo -n "Do you wish to continue? (Y/n) 5 seconds to respond... "
read -n 1 -t 5 answer # accepts a single character, 5 second timeout.
if [ "$answer" = "n" ] || [ "$answer" = "N" ] ; then
echo -e "\nExiting..."
exit
fi
echo -e "\nContinuing with script..."
# More code
read
的超时对我来说最重要 (read -t 5
)。读取的一个字符限制是可取的,但不是必需的 (read -n 1
)。
理想情况下,该脚本可以在 POSIX 系统上运行,也可以在 bash 内运行,而无需启用特殊的 POSIX 兼容模式。
stty
program provides the means to do this. xterm
有几个脚本(在其源代码的 "vttests" 子目录中)保存、修改和恢复终端设置以允许它读取终端对转义序列的响应。下面是dynamic2.sh
的一部分(开头设置printf
或echo
,用来解决一些旧系统用$CMD
变量):
echo "reading current color settings"
exec </dev/tty
old=`stty -g`
stty raw -echo min 0 time 5
original=
for N in $FULL
do
$CMD $OPT "${ESC}]$N;?^G${SUF}" > /dev/tty
read reply
eval original$N='${reply}${SUF}'
original=${original}${reply}${SUF}
done
stty $old
if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null
then
trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM
else
trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15
fi
根据 Dickey 先生的回答调整 stty 设置,如果按下 'n' 或 'N' 以外的任何内容,以下内容似乎有效并继续执行脚本。
据我所知,所有的 stty 设置都是 posix。
#!/bin/sh
read_char() {
old=$(stty -g)
stty raw -echo min 0 time 50
eval "=$(dd bs=1 count=1 2>/dev/null)"
stty $old
}
printf "Do you wish to continue? (Y/n) 5 seconds to respond..."
read_char answer
# answer=$(getch)
# answer=$(getche)
if [ "$answer" = "n" ] || [ "$answer" = "N" ] ; then
printf "\nExiting...\n"
exit
fi
printf "\nContinuing with script...\n"
替代"read_char":
这避免了使用 eval(可能不安全)
getch() {
old=$(stty -g)
stty raw -echo min 0 time 50
printf '%s' $(dd bs=1 count=1 2>/dev/null)
stty $old
}
这避免了 eval 并打印按下的键
getche() {
old=$(stty -g)
stty raw min 0 time 50
printf '%s' $(dd bs=1 count=1 2>/dev/null)
stty $old
}