为什么即使键码不是右箭头键,这也总是检测为真?
stty_state=`stty -g`
stty raw; stty -echo
keycode=`dd bs=1 count=1 2>/dev/null`
stty "$stty_state"
echo $keycode
if [ "$keycode"=39 ]; then
echo "Right Arrow Key Pressed!"
fi
Run Code Online (Sandbox Code Playgroud)
use*_*890 17
您(可能)首先读取了两个以上的字节。$keycode按下箭头键时,您的脚本中将是 ESC 。
箭头键可以是:
\x1b + some value
Run Code Online (Sandbox Code Playgroud)
由于条件表达式中缺少空格,它总是评估为真。
编辑:该声明的更新。
您if对[命令的退出状态进行操作。该[命令等效于test. 它是一个命令这一事实是一个非常重要的事实。作为命令,它在参数之间需要空格。该[命令更特殊,因为它需要]作为最后一个参数。
[ EXPRESSION ]
Run Code Online (Sandbox Code Playgroud)
该命令以 EXPRESSION 确定的状态退出。1 或 0,真或假。
这不是一种写括号的奇特方式。换句话说,它不是if语法的一部分,例如在 C 中:
if (x == 39)
Run Code Online (Sandbox Code Playgroud)
经过:
if [ "$keycode"=39 ]; then
Run Code Online (Sandbox Code Playgroud)
你发出:
[ "$keycode"=39 ]
Run Code Online (Sandbox Code Playgroud)
扩展到
[ \x1b=39 ]
Run Code Online (Sandbox Code Playgroud)
这里\x1b=39被视为一个论点。当testor[被赋予一个参数时,仅当EXPRESSION 为 null 时它才会以 false 退出——这是永远不会的。即使$keycode是空的,也会导致=39(非空/空)。
另一种看待它的方式是你说:
if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.
Run Code Online (Sandbox Code Playgroud)
阅读这些问题和答案以获取更多详细信息——以及关于[vs 的讨论[[:
在这方面,您还可以研究回拨`` vs $( )
带箭头键的多字节转义序列:
如顶部所述:您(可能)首先读取了两个以上的字节。$keycode按下箭头键时,您的脚本中将是 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
Run Code Online (Sandbox Code Playgroud)
屈服:
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
Run Code Online (Sandbox Code Playgroud)
不确定这有多便携,但之前曾使用过这样的代码来捕捉箭头键。按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
Run Code Online (Sandbox Code Playgroud)
(作为一个小提示,您还(打算)针对十进制 39 进行测试——这看起来像是十进制和十六进制之间的混合。转义序列中的第一个字节是ASCII 值 ESC,它是十进制27 和十六进制0x1b,而十进制39 是十六进制0x27。 )
| 归档时间: |
|
| 查看次数: |
10443 次 |
| 最近记录: |