Answers:
您(可能)会先读取两个以上的字节。$keycode
当您按下箭头键时,脚本中的ESC将为ESC。
箭头键可以是:
\x1b + some value
由于条件表达式中缺少空格,因此始终将其评估为true。
编辑:该声明的更新。
您if
以[
命令的退出状态进行操作。该[
命令等效于test
。它是命令这一事实是非常重要的事实。作为命令,它要求参数之间有空格。该[
命令的特殊之处在于它需要]
作为最后一个参数。
[ EXPRESSION ]
该命令以EXPRESSION确定的状态退出。1或0,对或错。
这不是写括号的奇特方法。换句话说,它不是if
语法的一部分,例如在C中:
if (x == 39)
通过:
if [ "$keycode"=39 ]; then
您发出:
[ "$keycode"=39 ]
扩展到
[ \x1b=39 ]
这里\x1b=39
被视为一个论点。当test
或[
给出一个说法是假退出只有当表达式为空-这是永远不会是。即使$keycode
为空,也将导致=39
(不为null /空)。
另一种查看方式是您说:
if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.
阅读这些问题和答案以获取更多详细信息-以及关于[
vs的讨论[[
:
在这方面,您还可以研究壁虱``vs $( )
带箭头键的多字节转义序列:
如顶部所述:您(可能)从两个以上的字节中首先读取。$keycode
当您按下箭头键时,脚本中的ESC将为ESC。
箭头键和其他特殊键会导致转义序列发送到系统。该ESC字节的信号是“这里来一些字节应该以不同的解释”。至于箭头键这将是ASCII [
其次是ASCII A
,B
,C
或D
。
换句话说,在处理箭头键时必须解析三个字节。
您可以尝试按以下方向进行检查:
{ stty_state=$(stty -g)
stty raw isig -echo
keycode=$(dd bs=8 conv=sync count=1)
stty "$stty_state"
} </dev/tty 2>/dev/null
printf %s "$keycode" | xxd
产量:
HEX ASCII
1b 5b 41 .[A # Up arrow
1b 5b 42 .[B # Down arrow
1b 5b 43 .[C # Right arrow
1b 5b 44 .[D # Left arrow
| | |
| | +------ ASCII A, B, C and D
| +--------- ASCII [
+------------ ASCII ESC
不确定它的可移植性,但是更早就使用了类似这样的代码来捕获箭头键。按q
退出:
while read -rsn1 ui; do
case "$ui" in
$'\x1b') # Handle ESC sequence.
# Flush read. We account for sequences for Fx keys as
# well. 6 should suffice far more then enough.
read -rsn1 -t 0.1 tmp
if [[ "$tmp" == "[" ]]; then
read -rsn1 -t 0.1 tmp
case "$tmp" in
"A") printf "Up\n";;
"B") printf "Down\n";;
"C") printf "Right\n";;
"D") printf "Left\n";;
esac
fi
# Flush "stdin" with 0.1 sec timeout.
read -rsn5 -t 0.1
;;
# Other one byte (char) cases. Here only quit.
q) break;;
esac
done
(作为次要说明,您还(打算)对十进制39进行测试–看起来像是十进制和十六进制之间的混合。转义序列的第一个字节是ASCII值ESC,它是十进制 27和十六进制0x1b
,而十进制 39是十六进制0x27
。 )
=
测试中的符号周围没有空格,因此将其简单地解析为非空字符串,因此为真。箭头键是多个字节的事实是一个单独的问题。
[
是内置命令,人们就会更快地理解为什么空间很重要。(使用括号而不是括号并不是bash的一种怪异方式。)必须立即用完。更新一次。